# Welcome to Garden!

Garden is a DevOps automation tool for developing and testing Kubernetes apps faster

{% hint style="warning" %}
[See here](https://docs.garden.io/bonsai-0.13) for the Garden 0.13 (Bonsai) docs.
{% endhint %}

Garden lets you spin up **production-like environments** for development, testing, and CI **on demand**. It enables teams to use the **same configuration** and workflows for **every stage of software delivery**—and dramatically **speeds up builds and test runs** via smart caching.

If there's something you can't find in our docs, we happily encourage you to checkout [Garden Discussions](https://github.com/garden-io/garden/discussions) and/or file an issue on [our GitHub repo](https://github.com/garden-io/garden). We're more than happy to help!

#### Overview

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>What is Garden</strong></td><td>A quick introduction to the how and why of Garden</td><td><a href="/pages/Y67g7G5mbJRrwfK5MsQv">/pages/Y67g7G5mbJRrwfK5MsQv</a></td></tr><tr><td><strong>Use Cases</strong></td><td>A look at the most common Garden use cases</td><td><a href="/pages/bn6pkkI54XjIcuoE3CpH">/pages/bn6pkkI54XjIcuoE3CpH</a></td></tr><tr><td><strong>Garden vs Other Tools</strong></td><td>The cloud native tooling space is complex—learn where Garden fits in</td><td><a href="/pages/OQmnKcEoiVHid1Ie8Ilq">/pages/OQmnKcEoiVHid1Ie8Ilq</a></td></tr></tbody></table>

#### Getting Started

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Quickstart</strong></td><td>Get started with Garden in less than 5 minutes using our example project</td><td><a href="/pages/U9mfygbOn1h3u6UTk7Ee">/pages/U9mfygbOn1h3u6UTk7Ee</a></td></tr><tr><td><strong>Basics</strong></td><td>A quick introduction to Garden basics</td><td><a href="/pages/CNwCUVLlSdx1p0VgnXhu">/pages/CNwCUVLlSdx1p0VgnXhu</a></td></tr><tr><td><strong>Next Steps</strong></td><td>Once you've kicked the tires with our quickstart example, come here to learn how to add Garden to your own project</td><td><a href="/pages/2U8qRjafDWNhvpKSRaGF">/pages/2U8qRjafDWNhvpKSRaGF</a></td></tr></tbody></table>

#### Using Garden

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Variables and templating</strong></td><td>An introduction to Garden's powerful templating functionality</td><td><a href="/pages/ZiA9MdKmuURkLHaqe3hm">/pages/ZiA9MdKmuURkLHaqe3hm</a></td></tr><tr><td><strong>Kubernetes</strong></td><td>Learn how to use Garden to build, deploy, and test your K8s apps</td><td><a href="/pages/F126VlgzTgFT9j3gvEyE">/pages/F126VlgzTgFT9j3gvEyE</a></td></tr><tr><td><strong>Reference docs</strong></td><td>The pages in this section container reference docs for different plugins and actions types</td><td><a href="/pages/pmmOlXdAE43cAJFKDt2n">/pages/pmmOlXdAE43cAJFKDt2n</a></td></tr></tbody></table>


# What is Garden

**Garden is a DevOps automation tool for developing and testing Kubernetes apps faster**. It ties together all the components of your stack—infrastructure, builds, services, tests—into a **graph** of actions that fully describe how your system is **built**, **deployed**, and **tested**.

This lets you spin up **production-like environments** for development, testing, and CI **on demand**. It also enables teams to use the **same configuration** and workflows for **every stage of software delivery**—and dramatically **speeds up builds and test runs** via smart graph-aware caching.

### Who is Garden for

Garden is for teams that run their workloads on Kubernetes and want a better experience around developing and testing. It assumes you have access to a Kubernetes cluster (either local or remote) and the configuration needed to build and deploy your services (i.e. Dockerfiles, manifests, Helm charts, etc).

Garden is used by:

* **Platform Engineers** who use Garden as an integral component of their internal development platform (IDP). Garden allows them to standardize configuration and workflows across teams with heterogeneous tech stacks and to abstract away the gnarly bits so that feature teams can focus on the fun stuff ([learn more](/overview/use-cases/jumpstart-idp)).
* **DevOps Engineers** who use Garden to build fast and portable CI pipelines ([learn more](/overview/use-cases/portable-ci-pipelines)).
* **Application Developers** who use Garden to develop and test in production-like environments that they can spin up on-demand, without waiting for CI ([learn more](/overview/use-cases/local-development-remote-clusters)).

### How it works

Garden Core is a standalone binary that can run from CI or from a developer’s machine. Its configuration framework allows you to codify a complete description of your stack using intuitive YAML declarations—making your workflows **reproducible and portable**.

Here's an example of simplified Garden config:

```yaml
# You can split config into multiple files and even across repositories!
kind: Project
name: my-garden-project
providers:
  - name: kubernetes
    context: my-k8s-ctx
---
kind: Deploy
name: db
type: helm
spec: # ...
---
kind: Build
name: api
type: container
---
kind: Deploy
name: api
type: kubernetes
dependencies: [build.api, deploy.db]
spec: # ...
---
kind: Test
name: e2e
type: container
dependencies: [deploy.api]
spec: # ...
```

Garden collects all of these descriptions, even across multiple repositories, into the Stack Graph—**an executable blueprint for going from zero to a running system in a single command**.

Garden then leverages your existing configuration (Helm charts, Kubernetes manifests, Dockerfiles, Terraform files, etc) and infrastructure to execute the graph **in any environment**.

#### The Garden CLI

Each of the four action kinds (Build, Deploy, Test, Run) has a corresponding command that you can run with the Garden CLI.

![Deploy project then deploy again in a different env. Note the different URLs](https://github.com/garden-io/garden/assets/5373776/bdac24a9-4e77-47f4-87dd-c68730fb601a)

For example, to create a preview environment on every pull request, simply add the following to your CI pipeline:

```yaml
garden deploy --env preview
```

Or say a developer wants to run an end-to-end test from their laptop as they code. Again, it’s simple:

```yaml
garden test --name e2e
```

Garden also has a special mode called "sync mode" which live syncs changes to your running deploys ensuring **blazing fast feedback while developing**. To enable it, simply run:

```yaml
garden deploy --sync
```

There are also utility commands for getting logs, exec-ing into services, publishing images, and more.

No matter how big your stack grows, these workflows stay consistent.

#### Caching

One of the most important features of Garden is its smart caching abilities. Thanks to the graph structure, Garden can calculate the version of any part of your system, while accounting for upstream dependencies.

**This ensures that the same image never needs to be built twice or the same test run twice.**

If the end-to-end test in the example above passes, Garden will know not to run it again if the code hasn’t changed. Since Garden factors in dependencies, it will however re-run the test if any of the upstream services under test are modified.

Most tools don’t have this granular understanding of the system and the choice is between running everything or nothing. With Garden you can be confident that tests run when they **need to,** but no more.

This alone can speed up your pipelines by orders of magnitude.

#### Templating

Garden has a powerful templating engine that allows you to set variables and enable or disable parts of the graph depending on your environment.

You might for e.g. deploy a development database with the Kubernetes plugin in development but use the Terraform plugin to provision a managed database for production.

This allows you to codify your entire stack and use the same workflows for all stages of software delivery.


# Garden vs Other Tools

The tooling landscape for cloud development has gotten a lot more crowded over the past few years. In this doc, we’ll put Garden in context by comparing and contrasting it with other types of tools and platforms.

In short, Garden automates the process of building, deploying, developing and testing applications in a way that’s simpler, faster and way easier to maintain than laboriously writing CI pipelines or shell scripts by hand.

On top of this, it’s got code syncing for live reloading during development, live log streaming and an intuitive web interface. It combines advanced CI automation with a first-class experience during development and debugging.

## CI systems (GitHub Actions, BuildKite etc.)

Garden is not intended to replace traditional CI systems—in fact, the most common use-case for Garden is calling it in CI!

Where Garden fits into CI pipelines is by taking care of building, deploying and testing a graph of components (and publishing the built images afterwards if needed).

Garden can greatly simplify the task of creating ephemeral environments for every pull request, deploying to a staging environment on merges to the main branch, and running test suites involving one or more runtime components (e.g. API tests, end-to-end tests and load tests).

Our users report that over time the amount of YAML in their CI pipeline definitions shrinks down to almost nothing, since deploying an entire environment or running an end-to-end test suite becomes just `garden deploy` or `garden test`.

On top of that, developers and DevOps engineers alike can run Garden from their dev machines to reproduce anything that goes wrong in CI. No need to repeatedly re-trigger pipelines just to see if your fix works—your laptop can now do anything your CI system can!

## PaaS (Heroku, Fly etc.)

PaaS (platform-as-a-service) offerings provide developers with simplified abstractions of the underlying platform (e.g. Kubernetes or AWS EC2), and often come with their own special-purpose tools (CLIs and the like).

In contrast, Garden isn’t a hosting platform at all. It builds, deploys and tests on your own infrastructure. Bring your own infrastructure, and Garden will take it from there.

Just point it at a Kubernetes cluster or your AWS/Azure/GCP account, and Garden will build, deploy and test your application using the Dockerfiles, Kubernetes manifests, Helm charts, Terraform stacks etc. that you’re already using in CI or production.

Our goal is to add automation on top of what you already have, not to abstract it away.

This has two main benefits:

1. It keeps Garden simple to use and understand—we’re not trying to reinvent the wheel when it comes to building, deploying and testing—we delegate to specialist tools like BuildKit, kubectl, Helm and Terraform to do what they’re best at.
2. It lets Garden work for any system, no matter how simple or complex. Since we’re not asking you to fundamentally change how you’re building, deploying or testing your application, you can always add Garden on top of it to bring advanced dev & testing automation to your project.

## Internal developer portals (Backstage, Cortex etc.)

These tools take a different approach to dev automation: After being configured by DevOps engineers, they provide a point-and-click way for developers to create environments or deploy specific components. This is a simple and easy-to-use approach for companies where developers prefer to abstract away the complexity of the underlying system during development.

Garden also enables developers to easily deploy an entire environment or a subset of components (via the garden deploy command).

But it also goes a lot further than just deploying environments:

* Testing is a built-in primitive in Garden.
* Live-reloading during development via code syncing, and building without going through CI.
* Garden can be run from your dev machine, without committing & pushing your changes! This is a big deal when you're working on a feature and need a rapid code/debug/test loop to stay productive.
* Live log streaming from running services during development.

All in all, Garden provides more out-of-the box functionality for the developer, and tries to automate not just the creation of environments, but to provide a first-class developer experience when writing, debugging and testing code ( the perfect companion to your editor/IDE of choice).

In short, Garden merges the capabilities of a CI system with that of a developer tool.

Another difference is that tools like Backstage and Cortex are typically adopted by platform teams, whereas Garden is typically adopted by lead developers or DevOps engineers on individual teams, i.e. the people who are directly involved with CI & dev automation for a given team.

## Deployment and IaC tools (Helm, kubectl, Terraform, Pulumi etc.)

We work together! Garden has plugins for deploying using Helm, kubectl, Terraform and Pulumi. Our philosophy is to work with the way your system is currently built, deployed and tested, and focus on being the graph automation and developer experience layer on top of those building blocks.

## Kubernetes dev tools (Okteto, Skaffold, Loft)

These tools take a more focused approach to solving specific problems in developing apps for Kubernetes, and also generally focus only on Kubernetes (there's no support for Terraform or Pulumi, for example).

Like Garden, they offer code syncing, building and deploying, but don't have a built-in notion of testing. They're not intended to do the heavy lifting in a complex CI pipeline, but they're good at what they do. They also tend to be simpler to understand and get started with than Garden.

## GitOps CD tools (Argo, Flux)

Garden works well with GitOps-based CD tools. In short, Garden helps with everything up to production deployments, which most users prefer to do with dedicated CD tools.

The process is usually something like this (using ArgoCD as an example):

1. A developer uses Garden to debug & test a feature in a production-like dev environment.
2. After the developer opens a PR, a CI pipeline calls the Garden CLI to deploy an ephemeral environment from the branch (via garden deploy), and run the full set of test suites (via garden test).
3. After the PR is approved, a pipeline uses garden publish to publish the built images to the production container registry, where they're picked up by e.g. the ArgoCD image updater.
4. ArgoCD then triggers the production deployment process and takes things from there.

## Custom deployment scripts

While custom scripts and other in-house tooling gives you complete control, it also means a lot more work for your team down the line. Scripts also tend to be brittle, and are hard to maintain and test when new components are introduced, or dependencies change.

Garden's Stack Graph means you can easily add or remove components and change their dependencies, and your pipelines automatically adapt (since the execution graph is automatically generated from your Garden configs).

Garden's Run actions (one of the four main action kinds, the others being Builds, Deploys and Tests) can also be used to wrap any script or tool that you'd like to call in your pipeline, so you always have a general-purpose escape hatch for any custom logic you need to run in your pipeline that doesn't fit easily into Garden's way of doing things.


# Use Cases

Learn more about common Garden use cases in this section. Each page contains a high level description of the use case with links to more resources.


# Isolated On-Demand Preview Environments

### Why isolated on-demand preview environments?

Most teams using Garden use Kubernetes for production. This means they already have their Dockerfiles, manifests and/or Helm charts.

Garden lets them re-use these resources to create isolated preview environments on-demand so that they can:

* Review changes for every pull request in a production-like environment
* Easily share work in progress, even before pushing their code
* Test out their changes as they develop

If your staging environment is a bottleneck where changes get queued up, isolated preview environments might be the solution.

{% hint style="info" %}
Check out [how Slite uses Garden](/overview/case-studies/slite) to clear up their once congested staging environment.
{% endhint %}

### How does it work?

![Deploy project then deploy again in a different env. Note the different URLs](https://github.com/garden-io/garden/assets/5373776/bdac24a9-4e77-47f4-87dd-c68730fb601a)

Developers run the `garden deploy` command from their laptops to create a preview environment in their own namespace in the team's remote Kubernetes cluster.

Similarly, Garden can be run from CI pipelines to create isolated preview environments with each pull request, using e.g. the pull request number to isolate the environment. For example, you may have a CI job that runs `garden deploy --env preview`.

Garden's powerful templating engine ensures that namespaces and hostnames are unique across users and CI runs—and Garden's smart caching ensures creating these environments is blazing fast.

### Key features

* **View URLs**, logs, and command history with the [Garden dashboard](https://app.garden.io)
* **Accelerate build times** with [Garden's Remote Container Builder](/using-garden-with/containers/building-containers) and smart caching
* **Isolate environments** with [Garden's template syntax](/features/variables-and-templating)

### How can my team get on-demand preview environments?

Teams typically [adopt Garden in a few phases](/misc/adopting-garden) and setting up on-demand preview environments tends to be the first one.

So with that in mind, these are the recommended next steps:

* Go through our [Quickstart guide](/getting-started/quickstart)
* Check out the [First Project tutorial](https://github.com/garden-io/garden/blob/latest-release/docs/tutorials/README.md) and/or [accompanying video](https://youtu.be/0y5E8K-8kr4)
* [Set up your remote cluster](/using-garden-with/kubernetes/remote-kubernetes)
* [Add actions](/using-garden-with/kubernetes) to build and deploy your project
* Follow our guide on [environments and namespaces](/guides/namespaces) to ensure each preview environment is isolated

### Further Reading

* [What is Garden](/overview/what-is-garden)
* [Adopting Garden](/misc/adopting-garden)
* [Variables and Templating](/features/variables-and-templating)

### Examples

* [Kubernetes Deploy action example project](https://github.com/garden-io/garden/tree/0.14.20/examples/k8s-deploy-patch-resources)


# Fast, Portable CI Pipelines that Run Anywhere

### Why portable pipelines?

If you find yourself waiting for an entire CI pipeline to re-run just because you updated a commit message, Garden might be the tool for you. It can be the difference between *hours* and *minutes* across all stages of software delivery.

Teams typically use Garden to run tests, create preview environments, and share team namespaces in long-lived Kubernetes clusters. The more teams use Garden, the faster your CI pipelines become because everyone contributes to a shared cache. This is particularly useful for end-to-end tests, which are often the longest running tests in CI.

Similarly, when developers run the test from their laptop, Garden will also skip running it in CI. Since the test runs in a remote environment and Garden knows the version of every single file, they can trust that the test does indeed pass. No need to run it again.

Simply by adding extra environments to your Garden project, you can use Garden for local development *and* for testing and deploying your project in CI.

### Key features

* **Cached builds and tests**: Garden caches your tests and builds so you **only run what has changed**. The result is dramatic reductions for CI run-times, typically *twenty minutes* to an *hour*.
* **Automatic environment cleanup**, **deep Insights into CI test, builds and deploys**, and **triggered CI runs** with [Garden Cloud](https://app.garden.io/plans)
* **Encode once, run anywhere**: [Garden's Workflows](/features/workflows) can be run from any environment, including local machines, CI servers, and cloud environments.
* **Visualize your CI/CD flow**: Use the [Garden dashboard](https://app.garden.io) to visualize your CI/CD pipeline, view logs, and track command history.
* **Accelerate build times**: With remote image builds, you can speed up your image build times significantly.

If you're already familiar with Garden and just want to get going, click any of the links above to set up your features.

### Resources

* Garden's [Quickstart](/getting-started/quickstart)
* [Using Garden in CircleCI](/guides/using-garden-in-circleci)
* Garden's official [GitHub Action](https://github.com/marketplace/actions/garden-action).

### Further Reading

* [What is Garden](/overview/what-is-garden)
* [Using the CLI](/guides/using-the-cli)
* [Variables and Templating](/features/variables-and-templating)
* [Adopting Garden](/misc/adopting-garden)


# Shift Testing Left

### Why shift testing left?

Most teams using Garden use Kubernetes for production. This means they already have their Dockerfiles, manifests and/or Helm charts.

Garden lets them re-use these resources so that developers can test in remote production-like environments *as they code*. This means:

* No more waiting for CI to see if integration tests pass
* Run and debug any test suite from your laptop *as you code*
* Easily write and maintain load tests, integration, and end-to-end tests with fast feedback loops
* Speed up your delivery cycle by shifting DAST and similar testing methodologies left

If your team is stuck in a commit, push, pray cycle, shifting tests all the way left can help break it.

{% hint style="info" %}
Check out [how Podium use Garden](/overview/case-studies/testing-microservices) to end-to-end test 130 services, hundreds of times per day.
{% endhint %}

### How does it work?

![Run a test that passes then run it again. Note that the second time it's cached.](https://github.com/garden-io/garden/assets/5373776/978db934-6728-430d-aa24-56b1b5b6fd4a)

Testing is a first class primitive in Garden and teams use the Test action to define the tests for their project. These tests are typically run as a Kubernetes Pod in a production-like environment but there are several different options, depending on how the project is set up.

Developers use the `garden test` command to run all or specific tests from their laptop in a remote Kubernetes cluster as they code. They can also enable live code syncing to ensure a blazing feedback loop as they iterate on tests.

Similarly, tests can be run from a CI pipelines using the same commands.

Garden's smart caching ensures that only the tests belonging to the parts of your system that changed are executed which can dramatically speed up your pipelines.

### Key features

* **Visualize your dependency graph**, streams logs, and view command history with the [Garden dashboard](https://app.garden.io)
* **Hot reload** your changes for a fast feedback loop while writing and debugging tests with [Code Synchronization](https://docs.garden.io/guides/code-synchronization)
* **Never run the same test twice** thanks to Garden's [smart caching](/overview/what-is-garden#caching)

### How can my team shift testing left?

Teams typically [adopt Garden in a few phases](/misc/adopting-garden) and shifting tests left is one of the main milestones.

So with that in mind, these are the recommended next steps:

* Go through our [Quickstart guide](/getting-started/quickstart)
* Check out the [First Project tutorial](https://github.com/garden-io/garden/blob/latest-release/docs/tutorials/README.md) and/or [accompanying video](https://youtu.be/0y5E8K-8kr4)
* [Set up your remote cluster](/using-garden-with/kubernetes/remote-kubernetes)
* [Add actions](/using-garden-with/kubernetes) to build and deploy your project

### Further Reading

* [What is Garden](/overview/what-is-garden)
* [Adopting Garden](/misc/adopting-garden)
* [Variables and Templating](/features/variables-and-templating)


# Local Development With Remote Clusters

### Why develop with remote clusters?

Most teams using Garden use Kubernetes for production. This means they already have their Dockerfiles, manifests and/or Helm charts.

Garden lets them shift these resources left, without introducing friction or cognitive overload to developers, so that they can:

* Run their entire project in the cloud *as they develop*, irrespective of its size
* Share build caches with their team so that no two developers have to wait for the same build
* Easily write and maintain integration and end-to-end tests
* Developers barely need any dependencies on their local machines and new developers can be on-boarded in minutes
* Catch "production" bugs before they end up in production

If you worry your laptop may catch fire next time you run docker compose up, remote environments might be for you.

{% hint style="info" %}
Check out [how Open Energy Market use Garden](/overview/case-studies/kubernetes-automation) to empower developers on K8s and reduce onboarding time by a whopping 500%.
{% endhint %}

### How does it work?

![Start the dev console, deploy in sync mode, and view progress in the dashboard](https://github.com/garden-io/garden/assets/5373776/914a7695-6453-4b34-becf-eab387e478a0)

Developers start their day by running `garden dev` and deploy their project into an isolated namespace in the team's Kubernetes development cluster, re-using existing config and manifests but overwriting values as needed with Garden’s template syntax.

Teams then use Garden’s sync functionality to live reload changes into running Pods in the remote cluster, without needing a full re-build or re-deploy on every code change. There’s typically a trade of between how realistic your environment is and the speed of the feedback but with Garden you can get both.

### Key features

* **Visualize your dependency graph**, streams logs, and view command history with the [Garden dashboard](https://app.garden.io)
* **Accelerate build times** with [Garden's Remote Container Builder](/using-garden-with/containers/building-containers) and smart caching
* **Hot reload** your code to containers running in your local and remote Kubernetes clusters for a smooth inner loop with [Code Synchronization](https://docs.garden.io/guides/code-synchronization).

### How can my team develop against remote clusters?

Teams typically [adopt Garden in a few phases](/misc/adopting-garden) and using remote clusters for inner loop development tends to be one of the last ones. Each phase solves a unique problem though so its well worth the journey.

So with that in mind, here are the recommended next steps:

* Go through our [Quickstart guide](/getting-started/quickstart)
* Check out the [First Project tutorial](https://github.com/garden-io/garden/blob/latest-release/docs/tutorials/README.md) and/or [accompanying video](https://youtu.be/0y5E8K-8kr4)
* [Set up your remote cluster](/using-garden-with/kubernetes/remote-kubernetes)
* [Add actions](/using-garden-with/kubernetes) to build and deploy your project
* [Configure code syncing](/features/code-synchronization) so you can live reload changes to the remote cluster

### Further Reading

* [What is Garden](/overview/what-is-garden)
* [Adopting Garden](/misc/adopting-garden)
* [Variables and Templating](/features/variables-and-templating)

### Examples

* [Kubernetes Deploy action example project](https://github.com/garden-io/garden/tree/0.14.20/examples/k8s-deploy-patch-resources)


# Jumpstart your Internal Developer Platform

### Why use Garden to build your Internal Developer Platform (IDP)?

When developing microservices, the cognitive load for a new developer to a team or project is very high. Not only does a developer need to set up their developer environment with the tools and scripts they'll need to contribute, they also need to coordinate with other teams to pull in any remote microservices they may call when testing a new feature or API.

The stack might contain a pre-configured Helm chart for a database, Terraform modules for infrastructure, Kubernetes manifests for services, and more, that teams can compose together to suit their needs. With Garden, you define any number of resources as infrastructure-as-code and services, then deploy them as one group, with one command: `garden deploy`.

### Key features

* **Visualize your microservice stack**, centralize logs, and view command history with the [Garden dashboard](https://app.garden.io)
* **Pluggable repositories** with [remote sources](/features/remote-sources)
* **Create re-usable templates** with [Config Templates](/features/config-templates)

If you're already familiar with Garden and just want to get going, click any of the links above to set up your features.

Navigate to [Examples](#examples) for a selection of pre-configured stacks you can use to quickly explore relevant features.

### Resources

* Pull in any number of remote repositories to collaborate across teams by setting up [Remote Sources](/features/remote-sources)
* Use [Config Templates](/features/config-templates) to vend development environments to all your developers
* If you're coming from Docker Compose, visit our [Migrating From Docker Compose](/guides/migrating-from-docker-compose) guide

### Further Reading

* [What is Garden](/overview/what-is-garden)
* [Using the CLI](/guides/using-the-cli)
* [Variables and Templating](/features/variables-and-templating)
* [Adopting Garden](/misc/adopting-garden)

### Examples

* [Remote sources example project](https://github.com/garden-io/garden/tree/0.14.20/examples/remote-sources)
* [kubernetes Deploy action type example with config templates](https://github.com/garden-io/garden/tree/0.14.20/examples/k8s-deploy-config-templates)


# Case Studies

Case studies from teams using Garden to improve their development workflows in the real world.


# 85% Faster Builds: OEM's Boost with Garden Cloud Builder

*By Ricky Vidrio | July 19, 2024*

Open Energy Market (OEM) is dedicated to helping businesses reduce short-term costs and make confident long-term decisions through a tech-driven approach to energy and sustainability. Previously, we highlighted how OEM utilized Garden's smart caching to achieve an impressive reduction in build times, cutting down from 30-40 minutes to just 10-15 minutes.

Dan Taylor, OEM's Director of Technology, emphasized the company's commitment to continuous delivery, operating on an "integrate little and often" philosophy. Despite these advancements, OEM encountered a new challenge as its development needs grew, and build times still posed a bottleneck. This case study explores how OEM tackled this challenge head-on by adopting Garden's Cloud Builder, leading to greater efficiency and productivity gains.

## Problem: The Build-Time Bottleneck

At Open Energy Market, the development team was experiencing significant delays due to slow build times. Each deployment took approximately 15 minutes, and with frequent updates occurring up to 12 times a day, the accumulated wait time severely impacted the team's productivity. This inefficiency led to developers' frustration and slowed the overall project progress.

## Solution: Leveraging Garden's Cloud Builder

To address the issue of slow build times, Open Energy Market chose to leverage Garden's Cloud Builder. The setup process was remarkably straightforward, involving just three lines in the configuration file. This simplicity allowed the team to quickly transition to Cloud Builder with minimal disruption, drastically reducing build times.

> "Our mean time for deployments is about 15 minutes each. Now it's a solid four."

## Results: Dramatic Improvement in Build Times

Adopting Cloud Builder brought about significant improvements in build times. For front-end applications that previously took up to 15 minutes to build, the times were reduced to a consistent four minutes. For frequent deployers like Dan and his colleague Tom, deployment times for many services were reduced to just two minutes, drastically enhancing their workflow.

Dan did not enable Cloud Builder for his Windows users right away, so there was a direct comparison of error rates after adopting Cloud Builder. The error rate for Mac users using Cloud Builder was reduced to approximately 0.1%, compared to the Windows developers who experienced five to six failures daily. This reliability ensured the CI pipeline became more robust, with significantly fewer infrastructure-related failures.

## Reflection: A Game-Changer for Development

The positive outcomes of adopting Cloud Builder at Open Energy Market were profound:

1. **Increased Productivity**: Developers saved approximately a day per week that was previously spent troubleshooting build failures.
2. **Enhanced Reliability**: The CI pipeline became more robust, with significantly fewer infrastructure-related failures.
3. **Cost Efficiency**: By avoiding the need for expensive custom deployments, OEM managed to optimize their resources better.
4. **Developer Satisfaction**: The feedback from developers using Cloud Builder was overwhelmingly positive.

Dan Taylor from Open Energy Market reflects on the value of Cloud Builder: *"The transition to Cloud Builder was seamless, and the impact on our productivity has been remarkable. It has saved us time and allowed our developers to focus on what they do best -- developing great software."*

By adopting Cloud Builder, Open Energy Market has solved their immediate problem and laid a strong foundation for future growth and efficiency.


# How Podium End-to-End Tests Hundreds of Services a Day

*October 3, 2023 — Valerie Slaughter*

> We now deploy and end-to-end test 130 services, hundreds of times per day. We could not have done that without Garden.
>
> — Drew Bowman, Sr. Software Engineering Manager at Podium

[Podium](https://www.podium.com/) provides local businesses with easy-to-use growth, communication, and payment tools.

Before they started using Garden in 2021, Podium's development team was only running a handful of end-to-end tests, and only against the production environment. Without a standard way of running services in CI, they weren't able to run end-to-end tests pre-merge.

Podium used Garden's dependency graph, called the Stack Graph, to standardize build and deployment processes so that the team could spin up the same production-like environments in CI as they could in development. This, along with Garden's smart test and build caching, helped Podium to run tests earlier and more often -- and much faster.

"We now deploy and end-to-end test 130 services, hundreds of times per day," Drew Bowman, Sr. Software Engineering Manager at Podium told us. "We could not have done that without Garden."

We talked to Bowman as well as Andrew Jensen, Sr. Software Engineer at Podium, about how they're empowering developers and streamlining testing.

## Problems: Lots of complexity, no way to manage it

> There were just too many services.

### Testing against production

When it came to running end-to-end tests, Podium's development team had no standard way of running services in CI, and so were left end-to-end testing against the production environment.

It was an inelegant system, Jensen told us. The QA team would be alerted by production test failures. But because tests didn't run on merge requests, it was easy for them to go out of sync with app code, which led to a high rate of false positive alerts -- and a tired QA team.

Podium needed to be able to run pre-production tests and in order to do that, first they would need a standard way to run their services.

### Laptops on fire

Podium's team relied heavily on local development. To work on a particular service, they would run it locally by cloning a repo called "platform" -- essentially a very large Docker Compose configuration file with a handful of shell scripts in subdirectories.

But Jensen knew it was untenable. "There were just too many services," he said. It was overloading their development laptops. "It would cause big time RAM issues and CPU issues, and even disk issues with creating tons of Docker images locally."

Podium needed a solution that would allow the team to work on individual services without their laptops burning up.

### Manual deployments

Before using Garden, Bowman said, there was no source of truth.

"We had created different sets of Docker compose files, scattered throughout different places, and they were never up to date," Bowman said. Simple processes were taking developers too much time.

Standardizing workflows and, ideally, automating them would mean huge time savings.

## Solutions: An executable dependency graph

> Defining things using Garden's framework has helped us to develop in a streamlined way.

### One source of truth

Garden's Stack Graph was the biggest game-changer for Podium. The Stack Graph created a blueprint of their system's services and dependencies, standardizing and automating the deployment process.

"When you automate something, you make it canonical," Jensen told us. "Defining things using Garden's framework has helped us to develop in a streamlined way."

Every time a team member builds, deploys, or tests, it's guaranteed to be the same.

### Production-like ephemeral environments for dev and CI

The Stack Graph allows developers to instantly spin up service- and dependency-aware environments with a single command.

"It makes it really easy for developers to just get going," Bowman said. "Developers don't have to be concerned with what their service does, as long as it fits in the framework. Garden guarantees it will start up, play nice with others, and work in dev and CI."

This empowers developers to run end-to-end tests much earlier -- and to trust that those tests will work the same in development, CI, and production.

### Build and test caching

Garden speeds up testing pipelines by selectively retesting and rebuilding only the parts of your stack that have changed. For remote environments, the test results are stored at the cluster level so that the entire team can share the cached results.

Garden's caching capabilities made it much faster for Podium to run tests.

### Hybrid development

With Garden, devs don't need to worry about installing, configuring, and running resource-intensive tools. Garden's environments run in remote Kubernetes clusters but have fast feedback loops that feel local.

"Moving to hybrid development with Garden made it so our laptops were not overheating and burning up," Jensen told us. "And we were able to become more productive as a result."

## Outcomes: From chaos to order

> Garden is cool and we like it.

### More reliable shipping with powerful CI automation

Garden, Jensen said, "effectively let us move from **testing in production** to **testing in CI, monitoring in production**."

With the Stack Graph, they were able to standardize the process to spin up an environment in CI, just like in dev.

Now, they use ephemeral environments to run end-to-end tests with Cypress against their core frontend repo, as well as most backend repos, on merge requests. They only run tests for the product areas being changed.

"We've been investing a lot in CI," Bowman told us. "And specifically CI and Garden environments for running end-to-end tests. And we built something that's really big and really powerful."

### Developer empowerment

"Garden has empowered our developers," Bowman told us. "Empowered them to onboard quickly, to test and run their code in a standard way."

With Garden, devs don't need to worry about installing, configuring, and running resource-intensive tools. That means shorter onboarding times, faster coding, and an icey cool computer.

Garden has "streamlined" Podium's development process, Bowman said, so the dev team could stay busy shipping cool features -- like an [AI assistant](https://www.podium.com/ai-assistant/) that can respond to online reviews, summarize calls, and more -- instead of wrangling internal tooling.

### Scalability: A balance between automation and abstraction

Bowman appreciates that Garden abstracts away some of the complexity of Kubernetes so that developers don't need to be K8s experts.

But, he notes, Garden strikes a balance between abstracting away complexity and providing smart automations to better navigate it. That means that when things go wrong, developers default to troubleshooting with Garden.

But if things stay hairy, developers can still use kubectl commands or the k9s dashboard when they need to. "There's that escape hatch to see what is happening at a lower level," Jensen told us.

"That's where the big scalability productivity gains come from," Bowman said, "having both options."


# How OEM Used Garden to Empower Developers on Kubernetes

*July 31, 2023 -- Valerie Slaughter and Lisa Lozeau*

Going cloud native can be a headache. Developer Dan Taylor knew that if he was going to move Open Energy Market onto Kubernetes, he would need smart abstraction and automations to preserve developer productivity -- and experience -- in the face of a more complicated tool chain.

"The most important thing we have is the developers. If they're burnt out and struggling, and day to day is difficult, it's not sustainable. You won't ship very often," Taylor said.

With Garden, developers didn't have to become Kubernetes experts: they could get a running system with a single command, while Garden handled the Kubernetes configuration behind the scenes. Adopting Garden not only improved the inner development loop, it also set the stage for OEM to scale their architecture and complexity without pain.

## Challenges: Kubernetes automations

> I realized the question wasn't, 'Can we use Kubernetes?' -- it was, 'Can we automate processes?'

### Migrating from .NET to K8s

[Open Energy Market](https://www.openenergymarket.com/) provides smart energy services that help companies across procurement, carbon reduction, and compliance.

As a .NET Windows house, OEM's team used Visual Studio almost exclusively. Going cloud native would bring a lot of benefits -- increased flexibility and resiliency -- but would also potentially lead to developers having to interface with many different tools, each with their own configurations and variables.

Preserving developer sanity and autonomy was top priority for Taylor. He wanted a dev tooling solution that would abstract away some of the complexity of K8s so devs could concentrate on their work.

### Slow builds and lack of visibility

"Our old system was horrendous," Taylor said. "Historically our builds were incredibly slow. We'd have 30- to 40-minute build times."

Taylor used to monitor GitHub all day, looking for builds that were broken or slow. He wanted to be able to identify roadblocks for the developer team more proactively with data on build times and the stack. This tedious task didn't always yield results.

## Solutions: Kubernetes without the complexity

> Developers just use Garden environments and get moving, which makes them a lot more productive.

### One config that runs everywhere

With Garden, Taylor was able to provide developers with just enough abstraction and automation to make the complexities of Kubernetes easier to manage. Garden allowed OEM to codify all their services and dependencies into the Stack Graph -- an executable blueprint for going from zero to a running system in a single command.

The Stack Graph can be deployed in every stage of development (dev, prod, QA) and works the same in every environment, eliminating configuration drift.

"The fact that the CI/CD pipeline runs the same on my machine, your machine, the cloud was a big draw," Taylor told us.

### Environments with baked-in services and dependencies

Developers can spin up production-like ephemeral environments with all dependencies and services baked in.

Rather than tangling with the complexities of Kubernetes, developers just spin up Garden environments and start coding. "It's in their stack" Taylor told us. "They don't have to reconfigure it. They don't have to figure stuff out. It makes them a lot more productive."

This doesn't just improve developer experience. It also makes onboarding new developers a breeze.

### Smart build and test caching

Garden's build and test caching means that only changed code is retested or rebuilt. Remember builds taking 30-40 minutes each? Neither does Taylor.

"Now, about 90% of builds take five minutes, which is brilliant," he told us. Faster builds keep developers moving instead of being stuck waiting.

### DevOps insights

Garden's DevOps Insights feature gives Taylor visibility into all builds, tests, and deploys executed by Garden. He can easily see the average time for a PR to build, what changes trigger longer build times, and signs that a developer is having a problem.

"It's not about seeing the output of each developer; it's about seeing that each developer is outputting something," Taylor explained. "Sometimes I know when developers are having problems before they do, because I'll see the failure rate increasing."

## Outcomes: Ship faster

> We've made Garden the first tool that a developer uses, because we want them to ship on their first day.

### 83% faster build times

OEM uses Garden's smart caching to reduce build times from 30-40 minutes to just 5 minutes. That's *83% faster*. With faster build times, OEM's team of nine people averages 40 to 50 builds a day.

"We operate on the 'integrate little and often' philosophy: continuous delivery," Taylor told us. "We're using Garden's blue-green deployment process for everything, and we're deploying six times a day."

### 500% faster developer onboarding

With Garden, Taylor told us, "We've taken what was a fourteen-day developer onboarding process down to about half a day."

Garden's dependency- and service-aware Stack Graph takes the manual labor out of getting up and running. "To install all the prerequisites on your laptop, you install Garden, you run a command, and it installs everything for you," said Taylor. "We've made Garden the first tool that a developer uses, because we want them to ship on their first day."

### Test automation

It's also easy to add new tools and services with Garden. OEM invested in test automation suites that run through Garden using [Playwright](https://playwright.dev/). They built the demo in only eight hours. "Without Garden, we would not know how to orchestrate those things," Taylor said.

The team was able to focus on Playwright, build a Docker container, and let Garden take care of the rest. "Garden accesses all the variables. It knows what's deployed in what environment. It just feels wonderful to work with. That's what we were looking for, that feeling of ease."

### Built-in scalability

Garden enables OEM to scale without adding complexity for the developers. It is pluggable, allowing a stack to grow without retooling or disrupting developers. This has made it easier for OEM to build a microservices architecture that supports both British and European versions of some services.

"If you're developing portfolio and you don't care about the net zero, or the calculations or the finance system, you don't need to interact with those parts of the system," Taylor said. Garden keeps track of services and dependencies so developers don't need to think about them at all.

"It makes sure that we can support growth," Taylor said.


# How Obligate relies on Garden's cloud dev environments

*April 11, 2023 -- Valerie Slaughter*

> *"I want development to be as close to production as possible and also be able to test any kind of feature in isolation. Garden enables that -- and makes you take for granted something that with another tool set would be really difficult to achieve."*

[Obligate](https://www.obligate.com/) combines deep legal and tech know-how with financial expertise to help build a new blockchain-based financial system. Promoting a fully-regulated approach, Obligate offers a decentralized platform for on-chain financing using bonds and commercial paper on Polygon.

When CTO Daniel Killenberger joined Obligate (then FQX) as lead developer in 2019, he knew they needed a tool to improve developer experience. He didn't want developers to be stuck in limbo waiting on slow pipelines and flaky tests, or frustrated by a painful debugging process.

Daniel was impressed by how Garden brought development and production closer together. "That's why I was so into Garden and the vision of Garden back in the day when we chose it," he told us. He knew it would be a game changer for developer experience -- and he made sure that Obligate was using Garden from the beginning.

His vision has paid off. With Garden, Obligate's engineers develop in production-like environments, run end-to-end tests as they code, and spin up preview environments for QA, expediting the feedback cycle.

We spoke to Daniel about how Garden has improved productivity and developer experience.

## Challenges

> *"Most devs experience a pipeline that will run for God-knows-how-long and the tests simulated have nothing to do with production."*

### Slow, unreliable feedback loops

Developers often struggle to get accurate feedback. "They write feature specifications, write the tests, and then aren't able to launch the software and see what it actually does," Daniel told us.

Often, even when test results come through, they are not reflective of the production environment. "Most devs experience a pipeline that will run for God knows how long and the tests simulated have nothing to do with production. So then if you merge to the master, the pipeline would be different and it would fail."

"I wanted the dev environment to be as close to production and also be able to test any kind of feature in isolation," Daniel said.

### Painful debugging

When it comes to debugging, Daniel told us, it can be difficult to tell what went wrong. Developers live out a detective story as they try to piece together a complete view of what happened.

"It's important to be able to go through all the acceptance criteria for tickets and have the ability to check that in isolation for each feature," Daniel told us.

### Configuration woes

Differences between development, testing, and production environments don't just cause flaky, unreliable tests.

Daniel told us that dealing with configuration drift can potentially be a major pain point when it comes to developer onboarding. "Having a local environment with a team and you have to send over env files or whatever is a huge pain in the ass," he said.

## Solutions

> *"Having a production-like dev environment and then also having those previews for us is incredibly valuable."*

### Production-like dev environments with shareable preview environments

Garden's production-like dev environments eliminate the differences between dev, test, and prod environments. Engineers can run end-to-end tests as they code. This creates faster feedback loops and puts an end to flaky tests.

"Most companies do not have the ability to even spin up a production-like local environment with preview environments," Daniel told us. With Garden, the team has come to take it for granted. "Having a production-like dev environment and then also having those previews for the QA process is incredibly valuable."

QA can spin up a preview environment with a single command (or UI click) at every stage of development.

### (Stack) Stream-lined debugging

Garden's Stack Streams provides a unified view of logs, traces, and events across your entire stack -- every build, task, test, and service to make it easy to fix issues. Working with Stack Streams, Daniel and his team were also able to expedite debugging and reduce frustration.

"Having all the logs in the window makes it very easy to follow the stream of data. As we have logs everywhere, we're able to just put it into perspective at what time which logs showed up," Daniel said. "It made debugging a lot easier."

### Unified config

Bonus: Using Garden has removed the hassle of exporting variables. "I've worked with Garden so much that I kind of forget how much of a hassle it is to send around variables," Daniel said.

He describes Garden Secrets as a game changer. "It just makes it convenient. You can give access and not leak any kind of secrets that may be sensitive and all that makes it very nice."

## Outcomes

> *"I'm still really bought into the vision that Garden has for what developer experience should be and how close developer environments should be to production environments."*

### Faster onboarding for new engineers

The ability to spin up production-like environments that are connected to remote services helps new engineers get up and running right away.

"It only takes us a couple of hours to basically have them set up with a GitHub account and a Garden account," Daniel told us. "Then you can immediately deploy your dev environments and have a couple of microservices all at once."

### High quality ships

With Garden's preview environments, Obligate has been able to improve its overall workflow, allowing engineers to test code as they write it and see results in real time.

This shift in the DevOps process has greatly increased the quality of Obligate's builds, while cutting the time spent on those builds significantly. Preview environments help to keep QA in the loop for feature and release testing.

### Better DevEx

Engineers spend less time waiting for CI, less time trying to smooth friction between environments, and less time fighting to debug. They spend more time in flow, more time efficiently making fixes, and more time shipping cool new features.

As part of its most recent launch, the Obligate platform recorded its first bond issuance. The issuance, which was conducted entirely on-chain without any banks involved, is seen as a major step forward in the mainstream adoption of blockchain-based borrowing and lending infrastructure. Going forward, Obligate will continue to bridge the worlds of DeFi and TradFi and increase access to financing on a global scale.

Garden has helped Obligate grow by providing a platform that allows them to take a good developer experience for granted.

"I'm still really bought into the vision that Garden has for what developer experience should be and how close developer environments should be to production environments," Daniel said. "And nowadays it fulfills that promise quite nicely and that's why we keep using it. It is totally worth it."


# Slite - "Garden is the best companion for a Kubernetes dev, from local envs to CD."

*June 8, 2021 — Mike Winters*

## How Slite uses Garden for more developer autonomy, better pre-release testing, and fewer production issues.

*Key Takeaways*

* Slite uses Garden to give every developer their own on-demand environment for pre-release testing, eliminating a major staging bottleneck that was hurting productivity
* QA teams, developers, and designers can now use shared environments during the pre-release review process, resulting in a better product with fewer issues in production
* Garden enabled Slite to move beyond Docker Compose and into the cloud when the application became too large to build and deploy on a laptop

## "Hey, can I have staging?"

It was a phrase that showed up so often in the company chat that it'd become a running joke amongst the engineering team. [Slite](https://slite.com/), a communication tool for remote teams, was growing quickly, and **that growth exposed bottlenecks in the development process**.

"We had just one production-like staging environment where engineers could test their changes before pushing," says Arnaud Rinquin, a senior developer at Slite. "And so we'd have to queue to wait our turn to use it. As the team grew, this waiting became unbearable."

## Developer independence via on-demand environments

The staging bottleneck was having a major impact on developer productivity, plus developers were rushing their pre-release testing so they could free up the shared environment as quickly as possible for the next person in line. Something had to change.

That's where Garden came in. Now, every developer at Slite can spin up their own production-like environment for testing whenever they need it.

"There's a lot less frustration on the dev team now because there are **far fewer bottlenecks**," Arnaud adds. "Our **developers are independent** and can work without constantly bumping into each other. They're autonomous, *and* they're **more confident about what they ship**, because they've tested thoroughly in a production-like setting."

## Better QA and design reviews for a better product

Garden has also enabled Slite to run a better QA and design review process before releasing to production.

"Having a shareable, production-like environment for pre-release user testing and design review has **increased the quality of our releases**. We used to realize *after* shipping that a feature wasn't optimal, but we're able to catch those issues beforehand now. With Garden, a developer and designer can sit together and share a **proper, real-life environment** during the review process."

## Beyond Docker Compose to smart in-cluster builds

Along with a revamp of their testing and QA processes thanks to ephemeral environments, what *first* brought Slite to Garden was a need to replace Docker Compose for local development.

"We had **too many services for Docker Compose to handle**, and the workload was too much for a single laptop. It was painful. We decided it was time to look for something so that **our developers could work in the cloud.** Garden's shared cache for building images—and all the time we'd save as a result—was the initial selling point for using Garden."

Slite's developers can now work on their service locally while running the rest of the stack in a Garden-powered environment in the cloud—a much more manageable workload for a laptop.

## Up next? Automated end-to-end testing with every pull request.

Slite currently uses Garden Enterprise to manage secrets across developers and environments. They next plan to take steps toward continuous deployment with Garden, taking advantage of triggered workflows to spin up an environment and run automated end-to-end and integration tests with every PR.

"The guidance we get from the Garden team is awesome and has been a huge value to us. **Garden is very responsive, but also very human and friendly.** It's not a stiff enterprise relationship that gives you the feeling you have to be wearing a suit to talk to them."

"The team provided fast support for everything from niche topics like generating wildcard TLS certificates, to fixing inefficiencies in our own Dockerfiles, and also providing workarounds for processes that aren't yet in Garden or are still experimental features."

What advice would Arnaud give to other users who are looking at Garden?

"If you use Kubernetes, at some point you'll need to upgrade your development tooling. Garden is the simplest solution that will cover all of your use cases from dev environments to continuous deployment. **Garden eliminates a lot of the complexity** and limits the choices you have to make by being an off-the-shelf, single solution—it has a wide scope. **It's the best companion for a Kubernetes developer, from local environments to CD, all in one tool.**"


# Quickstart

Garden is a DevOps automation tool for developing and testing Kubernetes apps faster.

In this quickstart guide, we'll:

* Install Garden
* Build an example project and (optionally) deploy it to a local Kubernetes cluster

#### Requirements

* Docker running on the system
* A local Kubernetes installation (optional)

If you don't have Kubernetes installed, you can check out our guide on [installing local Kubernetes](/guides/install-local-kubernetes) or simply skip the deploy step below and instead go to step 4b.

#### Step 1 — Install Garden

Install the Garden CLI for your platform:

{% tabs %}
{% tab title="macOS" %}

```sh
brew install garden-io/garden/garden-cli
```

{% endtab %}

{% tab title="Linux" %}

```sh
curl -sL https://get.garden.io/install.sh | bash
```

{% endtab %}

{% tab title="Windows" %}
Open PowerShell as an administrator and run:

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/garden-io/garden/master/support/install.ps1'))
```

We also recommend adding an exclusion folder for the `.garden` directory in your repository root to Windows Defender:

```powershell
Add-MpPreference -ExclusionPath "C:\Path\To\Your\Repo\.garden"
```

This will significantly speed up the first Garden build of large projects on Windows machines.
{% endtab %}
{% endtabs %}

For more detailed installation instructions, see our [Installation guide](/guides/installation).

#### Step 2 — Clone the example project

Next, we clone the example project from GitHub and change into the project directory:

```sh
git clone https://github.com/garden-io/quickstart-example.git
cd quickstart-example
```

#### Step 3 — Connect your project

Now we need to connect the project to the Garden Cloud backend. This is required to use features such as [team-wide caching](/features/team-caching) and the [Remote Container Builder](/features/remote-container-builder).

You connect the project via the login command like so:

```sh
garden login
```

You'll be asked to create an account if you haven't already. Once you've logged in an `organizationId` will be added to the project config. This is of course just an example project but in general you should check the Garden config file with the `organizationId` into your source control.

You can [learn more about connecting projects here](/guides/connecting-project).

#### Step 4a — Deploy the project to local Kubernetes

{% hint style="info" %}
If you don't have a local installation of Kubernetes you can skip this step and hop over to step 4b instead.
{% endhint %}

Now we can deploy the example project to our local Kubernetes cluster. We'll deploy the project in sync mode which enables live code syncing and starts the dev console:

```sh
garden deploy --sync
```

This will build all the containers in this project with the [Remote Container Builder](/features/remote-container-builder) and deploy them to your Kubernetes cluster. You can then visit the example project via [the port forward](http://localhost:9124) created by Garden. You can also see the build results in the [Builds UI](https://app.garden.io).

This example project also includes unit and integration tests. To run all tests in this project, type `test` in the dev console and hit enter (you can also run specific tests with e.g. `test unit` and `test integ`).

Once the tests pass, try running the same `test` command again. This time Garden should tell you all the tests have already passed at this version. It will also tell you that the container images are already built. That's Garden's smart caching in action and it can dramatically speed up CI pipelines and dev workflows.

<figure><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/garden-cache.png" alt="Garden caching"><figcaption><p>Garden test caching</p></figcaption></figure>

The project itself doubles as an interactive guide that walks you through some common Garden commands and workflows. You can open it via [the port forward](http://localhost:9124) created by Garden when you ran the `deploy` command with the `--sync` flag. We encourage you to give it a spin!

#### Step 4b — Build the project without Kubernetes

Even if you don't have Kubernetes you can still use the [Remote Container Builder](/features/remote-container-builder) to build the container images in this project.

To build the project, run:

```
garden build --env no-k8s
```

Garden will use the remote container builder to build the images. You can view the results in the [Builds UI](https://app.garden.io).

If you now run the `garden build --env no-k8s` command again, you should see that all the images are already built. That's Garden's smart caching in action and it can dramatically speed up CI pipelines and dev workflows.

<figure><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/garden-build-cache.png" alt="Garden caching"><figcaption><p>Garden build caching</p></figcaption></figure>

### Next Steps

Now that you have Garden installed and seen its basic capabilities it's time to take the next steps.

Start by checking out the [Garden basics guide](/getting-started/basics) which covers the main concepts that you need to understand.

After that you can either go through [first project tutorial](/tutorials/your-first-project) which explains step-by-step how to add Garden to an existing project. Or you can check out the [Next Steps guide](/getting-started/next-steps) which gives you a more high level but still step-wise overview of how to adopt Garden and add it to your stack.

If you have any questions or feedback—or just want to say hi 🙂—we encourage you to use [Garden Discussion](https://github.com/garden-io/garden/discussions)!

### Troubleshooting

If you get an error saying `Cannot connect to the Docker daemon at /path/to/docker.sock. Is the docker daemon running?`, make sure you have Docker running on your system and try again.

If you bump into other issues, don't hesitate to open a [GitHub issue in the Garden repo](https://github.com/garden-io/garden/issues).


# Garden Basics

Garden is a powerful tool but the basic concepts are quite simple. We highly recommend that you spend a few minutes reading through this guide to grasp them. If you do that, everything else that follows should feel quite intuitive.

### Anatomy of a Garden project

Every Garden project has the same structure: A project configuration and one or more actions.

As a convention, the project configuration is in a file called `project.garden.yml`, typically at the root of a given repo. A simple project configuration looks like this:

```yaml
# In project.garden.yml
apiVersion: garden.io/v2
kind: Project
name: my-project
environments:
  - name: dev
  - name: ci
```

This is also where you configure your *providers*. Providers are what enables you to use different action types. You e.g. need the `kubernetes` provider to use Helm actions.

So if you're using Garden to deploy to a Kubernetes cluster, you'd add the `kubernetes` or `local-kubernetes` provider configuration here. For example:

```yaml
# In project.garden.yml
apiVersion: garden.io/v2
kind: Project
name: my-project
environments:
  - name: dev
  - name: ci

providers:
  - name: local-kubernetes
    environments: [dev]
  - name: kubernetes # <--- Use a remote K8s cluster in CI
    environments: [ci]
    context: my-ctx
```

Garden projects also have one or more *actions*. These actions can be spread across the repo in their own config files, often located next to the thing they describe. A common way to structure a project is like this:

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/project-structure-file-tree-dark.png" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/project-structure-file-tree.png" alt="Garden project structure"></picture><figcaption><p>Garden project structure</p></figcaption></figure>

Note that Garden is very flexible and will work with whatever structure you currently have. It even works across git repositories! You can e.g. have your service source code in one repo and manifests in another. Or have your micro services split across multiple repos.

### Anatomy of a Garden action

Actions are the building blocks of a Garden project and describe how a given part of your system is built, deployed, or tested.

Every Garden action has the same common fields like `kind`, `name`,`type`, and a `spec` field that is specific to the action type.

**The type tells Garden how to execute it**. Garden will know to build `container` actions, install `helm` actions, apply `terraform` actions, and so on.

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/anatomy-of-action-dark.png" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/anatomy-of-action.png" alt="The anatomy of an action"></picture><figcaption><p>The anatomy of an action</p></figcaption></figure>

The true power of Garden lies in the fact that actions can depend on one another and reference outputs from other actions. Here's an example:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
environments: # <--- Specifying environments is required
  - name: dev
---
kind: Run
name: say-hello
type: exec
spec:
  command: ["echo", "Hello ${local.username}"]
---
kind: Run
name: say-what
type: exec
dependencies: [run.say-hello]
spec:
  command: ["echo", "Action say-hello says: '${actions.run.say-hello.outputs.log}'"]
```

If you now run:

```console
garden run say-what
```

...Garden will first run the `say-hello` action (because `say-what` depends on it) and then the `say-what` action which prints the output from `say-hello`:

```sh
Action say-hello says: 'Hello gardener'
```

**And that is essentially the core concept: Actions run in dependency order and can reference the output from each other.**

This is obviously a contrived example where we're using an action that just runs scripts. For real world projects these actions could be **containers, Helm charts and even entire Terraform stacks**. You tell Garden the "type", and it'll know how to execute it. That's how these simple concepts can be used to build very complex automations.

### Benefits

The example above that just runs simple scripts is pretty trivial but this same pattern allows you to build, deploy and test a system of any complexity in a single command. With a single Garden command you could for example:

* provision an ephemeral K8s cluster via Terraform and pass the output to other actions;
* then build and deploy all your services into an isolated environment in that cluster;
* then run your integration and end-to-end tests before tearing things down again.

You can add this command to a CI job, and just as easily run it from your laptop. You can also create re-usable config templates that you can share with your team.

Garden does more than just run the actions and interface with providers. It builds your containers faster thanks to our Remote Container Builder and caches the results of actions so that they don't run unless they have to, significantly speeding up the execution time.

The gif below shows the test caching in action:

![Run a test that passes then run it again. Note that the second time it's cached.](https://github.com/garden-io/garden/assets/5373776/978db934-6728-430d-aa24-56b1b5b6fd4a)

### Wrapping up

Don't worry too much about the different action kinds and types, we have plenty of examples to help you pick the right one. Just know that you can model a system of any complexity with this pattern, even if it's components are spread across multiple repos.

And if you have any questions, feel free to open an issue on Github or ask a question on [Garden Discussions](https://github.com/garden-io/garden/discussions).


# Next Steps

If you've kicked the tires with the [Quickstart guide](/getting-started/quickstart) you've seen how Garden lets you **spin up production-like environments for development, testing, and CI—with blazing fast caching**.

Now is the time to set up Garden for your own project to get these benefits and more.

This guide describes the main steps involved. It's meant as a roadmap for the configuration process with links to more in-depth resources. The configuration snippets are mostly for demonstration purposes to help you understand how your config evolves.

For a more high level guide of adopting Garden in your organization, check out our [Adopting Garden guide](/misc/adopting-garden).

## Step 1 — Create a project

The first thing you need to do is to create a project level Garden config file at the root of your project, typically called `garden.yml` or `project.garden.yml`.

Here's a simple example:

```yaml
# At the root of your project
apiVersion: garden.io/v2
kind: Project
name: my-project

environments: # <--- Every Garden project has one more environments
  - name: local
  - name: ci
```

## Step 2 — Configure Kubernetes provider

{% hint style="info" %}
Here we're assuming you're using Garden for Kubernetes workflows which is the most common use case. But you can also start with the [Terraform](/using-garden-with/terraform/configure-provider) or [Pulumi](/using-garden-with/pulumi/configure-provider) providers.
{% endhint %}

Next you need to tell Garden how to connect to your Kubernetes cluster by adding the relevant `provider` configuration to your project-level config file.

You can use [the local Kubernetes provider](/using-garden-with/kubernetes/local-kubernetes) if you have Kubernetes installed locally and [the Kubernetes provider](/using-garden-with/kubernetes/remote-kubernetes) for remote clusters (see config details in links).

At that point, your configuration will look something like this:

```yaml
# At the root of your project
apiVersion: garden.io/v2
kind: Project
name: my-project

environments:
  - name: local
  - name: ci

providers:
 - name: local-kubernetes
   environments: [local]
 - name: kubernetes
   environments: [ci]
   context: my-k8s-ctx
   # ...
```

## Step 3 — Add actions

Once you've configured your provider, it's time to add actions.

Actions are the basic building blocks that make up your Garden project. The different action types determine how they're executed.

For example, you can use the `container` Build action and the `kubernetes` or `helm` Deploy actions to build and the deploy a given service.

We recommend putting each action in its own `garden.yml` file and locating it next to any source files.

{% hint style="info" %}
Garden actions and their configuration can be spread across different files and even [across multiple git repos](/features/remote-sources).
{% endhint %}

Here's a simple example with actions for deploying an ephemeral database and an API server, and a Test action for running integration tests:

```yaml
# In db/garden.yml
kind: Deploy
name: db
type: helm
description: Install Postgres via Helm
spec:
  chart:
    name: postgresql
    repo: https://charts.bitnami.com/bitnami
    version: "11.6.12"
---
kind: Run
name: db-init
type: container
description: Seed the DB after it's been deployed
dependencies: [deploy.db]
spec:
  image: postgres:11.6-alpine
  command: ["/bin/sh", "db-init-script.sh"]

# In api/garden.yml
kind: Build
name: api
type: container
description: Build the api image
---
kind: Deploy
name: api
type: kubernetes
description: Deploy the api after its been built and the DB seeded
dependencies: [build.api, run.db-init]
spec:
  manifestFiles: [ api-manifests.yml ]
---
kind: Test
name: api-integ
type: container
description: Integration testing the api after its been deployed
dependencies: [build.api, deploy.api]
spec:
  image: ${actions.build.api.outputs.deploymentImageId}
  command: [./integ-tests.sh]
```

Depending on the size of your project, you may want to add a handful of actions to get started and then gradually add more as needed.

Once that's done, you can deploy your project to a production-like environment with:

```console
garden deploy
```

Similarly, you can run your integration or end-to-end tests in a production-like environment with:

```console
garden test
```

## Step 4 — Add more environments and providers

At this point, you should be able to deploy and test your project from your laptop in a single command with the Garden CLI.

Next step is to add more environments so you can e.g. create preview environments in your CI pipeline for every pull request.

You may also want to add our Terraform or Pulumi plugins if you're using those tools, following the same process as in step 2 and step 3 above.

Garden also lets you define variables and use templating to ensure the environments are configured correctly. Below is how you commonly configure environments with dynamic templating:

```yaml
# At the root of your project
apiVersion: garden.io/v2
kind: Project
name: my-project

environments:
  - name: local
  - name: dev
    defaultNamespace: my-project-dev-${kebabCase(local.username)} # <--- Ensure each developer has a unique namespace
  - name: ci
    defaultNamespace: my-project-ci-${git.commitHash} # <--- Ensure each CI run is in a unique namespace
    variables:
      hostname: ${git.commitHash}.my-company.com # <--- Ensure CI test environments are isolated by templating in the commit hash
  - name: staging
    variables:
      hostname: staging.my-company.com

providers:
  - name: local-kubernetes
    environments: [local]
  - name: kubernetes
    environments: [dev, ci]
    namespace: ${enironment.namespace} # <--- This is the defaultNamespace we configured above
    context: my-ci-cluster
    # ...
  - name: kubernetes
    environments: [staging]
    namespace: staging
    context: my-staging-cluster
    # ...
  - name: terraform # <--- Use the Terraform plugin for the staging environment to provision cloud managed services
    environments: [staging]

# In api/garden.yml
kind: Deploy
name: api
type: kubernetes
spec:
  manifestFiles: "[path/to/your/${environment.name}/k8s/manifests]" # <--- Pick manifests based on env
```

Now, you can create preview environments on demand from your laptop with:

```console
garden deploy --env dev
```

...or from your CI pipelines with:

```console
garden deploy --env ci
```

{% hint style="info" %}
[Garden Enterprise](https://app.garden.io/plans), our commercial offering, includes secrets management and RBAC to ensure you don’t need to add any secrets to your CI provider or setup secrets for development. This ensures 100% portability across all your environments.
{% endhint %}

Checkout our guide [in-depth guide on configuring environments](/guides/namespaces) for more details.

## Summary

And that's the gist of it!

We encourage you to try adding Garden to your own project. You won't need to change any of your existing code or configuration, only sprinkle in some Garden config files to codify your workflows and you'll be going **from zero to a running system in a single command**.

And if you have any questions, don't hesitate to reach out on [Garden Discussions](https://github.com/garden-io/garden/discussions).


# Your First Project

This tutorial walks you through the steps of adding Garden to a project. Our [example project](https://github.com/garden-io/web-app-example) is a three-tier web app that we'll be deploying to Kubernetes.

In the tutorial we'll:

1. [Create a Garden project](/tutorials/your-first-project/1-initialize-a-project)
2. [Pick our Kubernetes plugin and set it up](/tutorials/your-first-project/2-connect-to-a-cluster)
3. [Add actions to the project](/tutorials/your-first-project/3-add-actions)
4. [Add tests to the project](/tutorials/your-first-project/4-testing)
5. [Enable code syncing](/tutorials/your-first-project/5-code-syncing)
6. [...and discuss next steps](/tutorials/your-first-project/6-configure-your-project)

### Requirements

* You'll need to have Garden installed to follow along with this guide. You'll find the instructions in our [Quickstart guide](/getting-started/quickstart).
* We also recommend quickly reading the [Garden Basics](/getting-started/basics) page before carrying on.

Once you've done that, head on over to the [next page](/tutorials/your-first-project/1-initialize-a-project)!


# 1. Create a Garden Project

The first thing we'll do is create a Garden project. Remember that you need to have the [Garden CLI installed](/getting-started/quickstart#step-1-install-garden) to follow along.

## Step 1 — Clone the example application

Start by cloning the example repo and checkout to the `tutorial-start` branch:

```sh
git clone https://github.com/garden-io/web-app-example.git
cd web-app-example
git checkout tutorial-start
```

The example is a three-tier web app with web, API, and database components. Garden is typically used in projects with multiple microservices but we're keeping things simple here to make it easy to follow along.

## Step 2 — Create a project

Next, we'll create a project config file in the root of the example with:

```sh
garden create project --name web-app-example
```

This will create a basic boilerplate project configuration in the current directory, making it our project root. It will look something like this:

```yaml
apiVersion: garden.io/v2
kind: Project
name: web-app-example

defaultEnvironment: local

environments:
  - name: local
    defaultNamespace: web-app-example
    variables:
      hostname:
        "local.demo.garden"
  - name: remote-dev
    defaultNamespace: web-app-example-${kebabCase(local.username)}
  - name: ci
    defaultNamespace: web-app-example-${git.branch}-${git.commitHash}
  - name: preview
    defaultNamespace: web-app-example-${git.branch}

providers:
  - name: local-kubernetes
    environments: [local]
  - name: kubernetes
    environments: [remote-dev, ci, preview]
```

We have four environments (`local`, `remote-dev`, `ci`, and `preview`) and also two provider configurations (`local-kubernetes` and `kubernetes`).

## Step 3 – Enable Remote Container Builder (optional)

We highly recommend using our [Remote Container Builder](/using-garden-with/containers/using-remote-container-builder) which can significantly speed up container builds for your Garden projects.

To enable it, update your provider configuration like so:

```yaml
# In project.garden.yml
providers:
  - name: container # <--- Add this!
    gardenContainerBuilder:
      enabled: true
  - name: local-kubernetes
    environments: [local]
  - name: kubernetes
    environments: [remote-dev, ci, testing]
```


# 2. Pick a Kubernetes Plugin

In order to deploy our project, we (perhaps obviously) need somewhere to deploy it to.

Here we hit a bit of a fork in the road since we have a choice between:

1. Setting up a local Kubernetes cluster on our dev machine
2. Using our own remote cluster.

## Option 1 — Local Kubernetes

You can use a local installation of Kubernetes (e.g. K3s, Minikube or Docker for Desktop). It's great for getting started quickly but you'll miss out on all the collaboration and team features you get with a remote Kubernetes environment.

To use this option follow the steps below.

### Step 1 — Install Kuberneters locally

Follow our [local Kubernetes guide](/using-garden-with/kubernetes/local-kubernetes) to set up this plugin.

### Step 2 — Set default environment

Open the `project.garden.yml` file we created earlier and ensure the `defaultEnvironment` field is set to `local` like so:

```yaml
defaultEnvironment: local
```

## Option 2 — Your own remote Kubernetes cluster

This option requires more upfront work but is highly recommended for *teams* using Garden. It allows you to build, test, and develop in a remote production-like environment that scales with your stack and allows you to easily share work with your team.

If you want to get started quickly we recommend first going for **Option 1** above and then coming back to this one once you've kicked the tires.

Otherwise follow the steps below.

### Step 1 — Setup remote Kubernetes

Follow our [remote Kubernetes guide](/using-garden-with/kubernetes/remote-kubernetes) to set up this plugin.

In particular you'll need to update the values under the `kubernetes` provider in the `project.garden.yml` file we created earlier.

### Step 2 — Enable Remote Container Builder (optional)

We highly recommend using our [Remote Container Builder](/using-garden-with/containers/using-remote-container-builder) which can significantly speed up container builds.

### Step 3 — Update the default environment

Open the `project.garden.yml` file we created earlier and update the `defaultEnvironment` field like so:

```yaml
defaultEnvironment: remote-dev
```

## Next Step

Once you've set up your Kubernetes plugin and updated your project configuration accordingly, you can move on to [adding Garden actions to the project](/tutorials/your-first-project/3-add-actions).


# 3. Add Actions

With our Kubernetes environment set up, we can start adding Garden actions for building and deploying our project.

### Step 1 — Log in to Garden Cloud

Start by logging into Garden Cloud with:

```sh
garden login
```

This enables you to use our [Remote Container Builder](/using-garden-with/containers/using-remote-container-builder) which can significantly accelerate container builds as well as benefit from team-wide caching.

It also allows you to use your [Builds UI](https://app.garden.io) to view build logs analyze build bottlenecks.

{% hint style="info" %}
You can skip logging in if you choose but if you don't, you won't be able to use the Remote Container Builder nor benefit from the team-wide caching functionality.
{% endhint %}

### Step 2 — Add actions for deploying the database

Next, let's add Garden actions for deploying the database.

First, create a `garden.yml` config file in the `./db` directory.

We'll use actions of *kind* `Deploy` and `Run` to deploy and seed the database. Each action also has a *type* which determines how it's executed and depends on the plugins that we're using.

Since this is for a development environment we can deploy the database directly to our Kubernetes cluster. Let's use a Postgres Helm chart and add a Deploy action of type `helm`.

Now add the following to `./db/garden.yml`:

```yaml
kind: Deploy
name: db
type: helm
description: Deploy a Postgres Helm chart
spec:
  chart: # <--- Tell Garden what chart to use
    name: postgresql
    repo: https://charts.bitnami.com/bitnami
    version: "12.4.2"
  values: # <--- Overwrite some of the chart values
    fullnameOverride: postgres
    auth:
      postgresPassword: postgres
    primary:
      readinessProbe:
        successThreshold: 3
---
kind: Run
name: db-seed
type: kubernetes-exec
dependencies: [deploy.db]
description: Execute a command to initialize the database inside the running deployment
spec:
  resource: # <--- The K8s resource in which the action should be executed
    kind: "StatefulSet"
    name: "postgres"
  command: # <--- A simple command that creates a table that our app needs
    [
      "bin/sh",
      "-c",
      "PGPASSWORD=postgres psql -w -U postgres --host=postgres --port=5432 -d postgres -c 'CREATE TABLE IF NOT EXISTS votes (id VARCHAR(255) NOT NULL UNIQUE, vote VARCHAR(255) NOT NULL, created_at timestamp default NULL)'",
    ]
```

Here we're using the `kubernetes-exec` action type to seed the database by executing a command inside the running Pod. This is a good choice for development but another common pattern is to run separate Pods for these kind of one-off operations, e.g. via a `container` Run action.

Note also the `resource` field which tells Garden what resource to execute the command in.

{% hint style="info" %}
For higher environments we recommend using our [Terraform](/using-garden-with/terraform) or [Pulumi](/using-garden-with/pulumi) plugins to deploy a proper managed database instance.
{% endhint %}

### Step 3 — Add a Build action for the API

Next, let's add actions for the API.

This time we'll use actions of *kind* `Build` and `Deploy` to (unsurprisingly) build and deploy the API.

First, create a `garden.yml` config file in the `./api` directory.

Then add the following Build action to the file:

```yaml
kind: Build
name: api
description: Build the API image
type: container
```

Now, try building the API by running the following from the interactive dev console:

```console
garden build
```

You can view the results and the logs in [Garden Cloud](https://app.garden.io).

Try running the `garden build` command one more time. Notice how Garden checks the status of the action and tells you that the API is already built?

This is how you can share build caches with your entire team when using the Remote Container Builder. Once a given part of your system has been built, everyone else on the team—and your CI pipelines—can re-use it and save massive amounts of time otherwise spent waiting for builds.

{% hint style="info" %}
By default, Garden will look for a Dockerfile next to the Garden config file but you can configure this. See [here](/reference/action-types/build/container#spec-dockerfile) and [here](/misc/faq#can-i-use-a-dockerfile-that-lives-outside-the-action-directory).
{% endhint %}

### Step 4 — Add a Deploy action for the API

Next, we'll add an action for deploying the API.

Since we already have Kubernetes manifests for the API in the `./manifests` directory we'll use the `kubernetes` action type and add the following below the Build action in `./api/garden.yml`:

```yaml
---
kind: Deploy
name: api
type: kubernetes
description: Deploy the API
dependencies: [build.api, run.db-seed] # <--- We need to build the api and seed the DB before deploying it

spec:
  manifestTemplates: [./manifests/*] # <--- Tell Garden what manifests to use

  defaultTarget: # <--- This tells Garden what "target" to use for logs, code syncing and more
    kind: Deployment
    name: api

  # Patch the K8s manifests for the api service so that we can set the correct image
  patchResources:
    - name: api
      kind: Deployment
      patch:
        spec:
          template:
            spec:
              containers:
                - name: api
                  image: ${actions.build.api.outputs.deploymentImageId} # <--- Reference the output from the Build action
```

Note the `patchResources` field. When Garden builds the API it attaches a version to the image based on the version of that action (which is based on the source code and action configuration). To ensure we deploy the correct version of the action we overwrite the `image` field in the corresponding manifest by applying the `patch` we specify under the `patchResources` field.

There are a few ways to overwrite manifest values with Garden but this is the recommended approach since it allows you to re-use existing manifests without making any changes to them. You can learn more about the different approaches [here](/using-garden-with/kubernetes/deploy-k8s-resource#overwriting-values).

Next, lets deploy the API with:

```console
garden deploy
```

### Step 5 — Add actions for the web service

The actions for the web service will be very similar.

First, create a `garden.yml` file in the `web` directory and then add the following:

```yaml
kind: Build
name: web
type: container
---
kind: Deploy
name: web
type: kubernetes
dependencies: [build.web, deploy.api]
spec:
  manifestTemplates: [./manifests/*]

  # Default target for syncs and exec commands
  defaultTarget:
    kind: Deployment
    name: web

  # Patch the K8s manifests for the web service so that we can set the correct image
  patchResources:
    - name: web
      kind: Deployment
      patch:
        spec:
          template:
            spec:
              containers:
                - name: web
                  image: ${actions.build.web.outputs.deploymentImageId}
```

If you have a lot of actions with similar config, you can create [reusable Config Templates](/features/config-templates) to avoid the boilerplate.

Now try deploying the entire project by running the following from the interactive dev console:

```sh
garden deploy
```


# 4. Add Tests

Garden treats tests as a first class citizen and has a dedicated Test action kind. Let's add one for integration/end-to-end testing our project.

## Step 1 — Add a Test action

In the `./web/garden.yml` file, add the following below the Deploy action:

```yaml
---
kind: Test
name: integ
type: container
dependencies: [deploy.web]
spec:
  image: ${actions.build.web.outputs.deploymentImageId}
  command: [npm, run, test:integ]
```

This action depends on the web service being deployed and will basically sit at the edge of the graph.

## Step 2 — Run the test

Next, run the test with:

```
garden test
```

When you have multiple tests in your project you can also specify which one to run with `garden test my-test-name`.

Once the test passes, try running it again.

Notice how Garden tells you that the test has already passed?

This is Garden's caching mechanism at play. Garden knows exactly what files and configuration goes into each action (including upstream dependencies) and stores the version and results of each execution.

This can mean massive time savings for large projects, in particular in CI, where only the tests for the parts of the system that actually changed need to be re-run.

## Step 3 – Break the test

Let's convince ourselves this works as expected. Open the `./api/app.py` file and break the test by changing the following line:

```python
if request.method == 'POST':
```

to:

```python
if request.method == 'PUT':
```

Even though the test itself is defined in the `./web/garden.yml` file, Garden knows that it depends on the API and that it needs to be re-run.

Try running it again with:

```console
garden test
```

If you now undo the changes and change the `request.method` back to `POST` and run the test one more time, Garden will again tell us that it has already passed since now the action version should be the same as it was before.


# 5. Code Syncing (Hot Reload)

So far we've set up our Kubernetes plugin and added actions for building, deploying, and testing the project.

You can think of these actions as blueprints for how to go from zero to a running and tested system in a single command. This allows you to remove most of the boilerplate from your CI pipelines and replace it with jobs that only have steps like `garden deploy` or `garden test`. And since you can run these same commands from anywhere, it's easy to debug these pipelines from the comfort of your laptop.

However, despite Garden's powerful caching functionality, building containers and redeploying services after you make changes to code or config can still be a slow process.

So as a final step, let's enable code syncing (i.e. hot reloading) which means that changes we make to our code get live synced to the running service without requiring a rebuild or a redeploy.

## Step 1 — Add the sync config to the API Deploy action

We'll start by adding the sync config to our API Deploy action by adding the following below the `defaultTarget` field (under the `spec` field) in `./api/garden.yml`:

```yaml
  sync: # <--- Add this
    paths:
      - sourcePath: .
        containerPath: /app
        mode: "one-way-replica"
    overrides:
      - command:
          ["/bin/sh", "-c", "ls /app/app.py | entr -r -n python /app/app.py"]
```

The `paths` field is an array where you can specify different syncs for the action. In most cases you'll only need one entry where you specify the relative source path on your local file system and the absolute target path in the container. For more advanced use cases such as reverse syncs you can add more items to the `paths` array.

The `overrides` field allows you to specify various overrides that should only be applied when Garden is in sync mode. Here we're overriding the command that's used to start the container. Usually the container starts up with the `python /app/app.py` command but in sync mode we start it with a tool called `entr` to manage the process and restart it on changes. Depending on your language and ecosystem, you'll have different choices here.

Note that this also works for compiled language but an extra compilation step may need to be added. The rule of thumb is that whatever workflows you currently use to rapidly rebuild your project during development can be used here.

Note also the `defaultTarget` field we added previously. This is how Garden knows what "target" to sync changes to.

[See here](/features/code-synchronization) for an in-depth guide on code syncing for different action types.

## Step 2 — Add the sync config to the web Deploy action

The sync spec for the web component looks similar. Add the following to `./web/garden.yml`:

```yaml
# In ./web/garden.yml
  sync:
    paths:
      - sourcePath: ./src
        containerPath: /app/src
        exclude: [node_modules]
    overrides:
      - command: [npm, run, dev]
```

Here we're also using the `exclude` field to exclude the local `node_modules` directory.

## Step 3 — Deploy in sync mode

Now let's deploy the project in sync mode by running the following from the interactive dev console:

```console
deploy --sync
```

If you don't have the dev console running you can also run:

```console
garden deploy --sync
```

...which will start the console and automatically run `deploy --sync` within it in a single command.

## Step 4 — Verify that code syncing works

Finally, let's verify that syncing works as expected by turning on logs for these services by\
running the following in the dev console:

```
logs --follow
```

{% hint style="info" %}
You can turn off logs in the dev console with `hide logs`.
{% endhint %}

You can also stream them in a separate terminal window by just running `garden logs --follow`.

Now open the `api/app.py` file in your IDE and try changing the string in the `print("Starting API")` statement near the start of the file. You should see in the logs that the API server restarts and that the new log line is printed.

Next try opening the voting application itself by following the link in the dashboard. You'll see that it has green and red background colors.

Now open the `web/src/colors.js` file in your IDE and try changing the colors. Notice that the voting app updates immediately, despite running in a Kubernetes cluster.

One other way to test syncing is by shelling into the running Pod and verifying that the files have updated with the Garden `exec` utility command. To e.g. shell into the API, run the following from a separate terminal window (exec doesn't work inside the dev console):

```console
garden exec api /bin/sh
```

This gives us shell access to the API that we can use to look around or run commands.


# 6. Next Steps

And that's a wrap!

With the example project all set, you can start thinking about your own project. The steps will be similar, and some work you won't need to repeat.

Garden is a powerful and flexible tool, and there are several things to learn along the way. We recommend the following to get going:

1. Place the project configuration you created for the example, which will already be configured to connect to your cluster, in your own project root.
2. Start adding your own actions, and get them building and deploying. Consider using [ConfigTemplates](/features/config-templates) if you have a lot of similar actions configs.
3. Add more environments. Garden works great in CI and in fact that's often the starting point for many teams. Take a look at our [guide on environments and namespaces](/guides/namespaces) to learn more.

In summary, **gradually put all the pieces together**, learn the details as you go, and use more and more features as you get comfortable.

For a large, complex project, it might be good to start with a subset of it, so that you can start getting value out of Garden quickly.

Whatever your setup is, we're sure you'll be rewarded with an elegant, productive setup for testing and developing your system!

And if there's something you can't find in our docs, we happily encourage you to [check out Garden Discussions](https://github.com/garden-io/garden/discussions) and/or file an issue on [our GitHub repo](https://github.com/garden-io/garden). We're more than happy to help!


# Setting up a Kubernetes cluster

## Requirements

To use the (remote) `kubernetes` plugin, you'll need the following:

* A Kubernetes cluster.
* Permissions to create namespaces and to create deployments, daemonsets, services and ingresses within the namespaces created.
* A container registry that Garden can push images to and\
  that your cluster can pull images from.
* Ingress and DNS set up.

The following pages walk you through setting these up step-by-step, but feel free to skip over the steps you don't need.

Also note that there are a lot of ways to create these resources so feel free to use whatever approach you find most useful.

At the end of these steps, you should have the following values at hand:

* The context for your Kubernetes cluster ([see step1](/tutorials/remote-k8s/create-cluster)).
* The name(s) and namespace(s) of the ImagePullSecret(s) used by your cluster ([see step 2](/tutorials/remote-k8s/configure-registry)).
* The hostname for your services ([see step 3](/tutorials/remote-k8s/ingress-and-dns)).
* A TLS secret (optional) ([see step 3](/tutorials/remote-k8s/ingress-and-dns)).

You will use these when configuring the `kubernetes` plugin. The configuration will\
look something like this:

```yaml
apiVersion: garden.io/v2
kind: Project

environments:
  - name: remote
    variables:
      hostname: <THE HOSTNAME FROM STEP 3>

providers:
  - name: kubernetes
    environments: [remote]
    imagePullSecrets:
      - name: <THE IMAGE PULL SECRET FROM STEP 2>
        namespace: <THE IMAGE PULL SECRET NAMESPACE FROM STEP 2>
    deploymentRegistry:
      hostname: <THE REGISTRY HOSTNAME CONFIGURED IN STEP 2>
      namespace: <THE REGISTRY NAMESPACE CONFIGURED IN STEP 2>
    context: <THE KUBE CONTEXT FROM STEP 1>
    buildMode: cluster-buildkit
    defaultHostname: <THE HOSTNAME FROM STEP 3>
```


# 1. Create a Cluster

First things first, you'll need a Kubernetes cluster you can deploy to.

At the end of this step you should have the context of your Kubernetes cluster at hand.

You should also have permissions to create namespaces in your cluster, and to create Deployments, Daemonsets, Services, and Ingresses within the namespaces.

Below you'll find basic guides for some common cloud providers:

* [AWS](/tutorials/remote-k8s/create-cluster/aws)
* [GCP](/tutorials/remote-k8s/create-cluster/gcp)
* [Azure](/tutorials/remote-k8s/create-cluster/azure)

Let us know on [Garden Discussions](https://github.com/garden-io/garden/discussions) if you'd like guides for more providers.

Note that there are multiple ways to create Kubernetes clusters (e.g. point-and-click, Terraform, Pulumi, etc) and feel free to pick whatever approach you're most comfortable with.

As long as you have a cluster and are able to perform basic operations on it with kubectl, you should be good to go.


# AWS

## AWS (EKS)

The official [AWS EKS user guide](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) guides users to create their cluster using the official `eksctl` tool.

### tl;dr

The following command will create an EKS cluster with a managed node group using any AWS instances that meet the criteria of 4 vCPUs and 16 GiB of memory. It uses IAM Roles for Service Accounts (IRSA) to attach a policy to the cluster allowing power user access to AWS' Elastic Container Registry. Visit the docs for more details on the [AmazonEC2ContainerRegistryPowerUser policy](https://docs.aws.amazon.com/AmazonECR/latest/userguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonEC2ContainerRegistryPowerUser).

```bash
eksctl create cluster -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: $USER-cluster
  region: $AWS_REGION

managedNodeGroups:
- name: mng
  instanceSelector:
    vCPUs: 4
    memory: 16

iam:
  withOIDC: true
  serviceAccounts:
  - metadata:
      name: ecr-poweruser
      # set namespace to your developer namespace
      namespace: $USER-dev
    attachPolicyARNs:
    - "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser"
EOF
```

## Permissions

IAM users or roles need the following AWS permissions to interact with your EKS cluster:\
eks:DescribeCluster\
eks:AccessKubernetesApi

You can select these when creating the policy through the UI, or with this JSON version:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "eks:DescribeCluster",
                "eks:AccessKubernetesApi"
            ],
            "Resource": "<arn identifier>"
        }
    ]
}
```

You will also need a Kubernetes role and service account in the EKS cluster. This can be achieved with the aws-auth configmap. The [instructions are documented here](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html). If you are interested in minimizing the permissions in the cluster, please take a look at our [Kubernetes RBAC guide](/guides/rbac-config).


# GCP

## Create a project and a cluster

First, follow the steps in [GKE's quickstart guide](https://cloud.google.com/kubernetes-engine/docs/quickstart?authuser=1) to create a project (if you haven't already) and a Kubernetes cluster.

You can create a cluster either using the `gcloud` CLI tool, or through the web UI—whichever you find more convenient.

> Note: If `gcloud` throws unexpected permission-related errors during this process, make sure you've been authenticated via `gcloud auth login`.

Make sure to run

```sh
gcloud container clusters get-credentials [your-cluster-name]
```

to add an entry for your cluster to your local Kubernetes config.

If you run `kubectl config get-contexts`, the table shown should include a context with a `NAME` and `CLUSTER` equal to the cluster name you chose previously.

Select this context if it isn't already selected.

Run `kubectl get ns` to verify that you're able to connect to your cluster.

## Permissions

When using a GKE cluster with Garden, you can use the following [predefined roles](https://cloud.google.com/kubernetes-engine/docs/how-to/iam#predefined):

* Kubernetes Engine Developer
* Kubernetes Engine Cluster Viewer

These roles allow users to list all GKE clusters in a project and access the Kubernetes API and objects inside clusters.

To ensure that developers only have access to a single kubernetes cluster, create a separate project for that cluster.


# Azure

## AKS

In AKS' web UI under **Kubernetes Services**, choose **Create Kubernetes Service**.

Fill out the project & cluster details.

Install Azure CLI tools (see [the official docs](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest) for platform-specific instructions).

Now run:

```sh
az login
az aks get-credentials --resource-group [your resource group] --name [your cluster name]
```

This will merge an entry for your Azure cluster into your local Kubernetes config.

If you run `kubectl config get-contexts`, the table shown should include a context with a `NAME` and `CLUSTER` equal to the cluster name you chose previously.

Select this context if it isn't already selected.

Run `kubectl get ns` to verify that you're able to connect to your Azure cluster.


# 2. Configure Container Registry

You'll need a container registry to be able to push and pull your container images. We typically refer to this as a **deployment registry**.

Garden needs access to the registry so that it can *push* the images that it builds and your Kubernetes cluster needs access so that it can pull the images. This access is provided via an "image pull secret". It can be a single secret used by both or two (or more) secrets.

At the end of this step you should have a container registry set up, created an image pull secret (or secrets), and have the following values at hand:

* The name of the image pull secret (or secrets).
* The name of the namespace were you created the image pull secret (or secrets).
* The hostname of your container registry.
* The "namespace" name for your container registry.

{% hint style="info" %}
The registry hostname and namespace name part of the fully qualified container image name. For example, the fully qualified name for the busybox image is `registry.hub.docker.com/library/busybox` where `registry.hub.docker.com` is the hostname and `library` is the namespace.
{% endhint %}

Below you'll find guides for specific cloud providers:

* [AWS](/tutorials/remote-k8s/configure-registry/aws)
* [GCP](/tutorials/remote-k8s/configure-registry/gcp)
* [Azure](/tutorials/remote-k8s/configure-registry/azure)
* [Docker Hub](/tutorials/remote-k8s/configure-registry/docker-hub)

As always, feel free to pick a different approach. The end goal having a container registry that Garden can push to and that your cluster can pull from.


# AWS

## Setting up an ECR registry

Follow [this guide](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html) to create a private ECR registry on AWS.

Then follow [this guide](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) to create an image pull secret so that your cluster can pull images from your registry.

Make note of the ImagePullSecret name and namespace.

## Enabling in-cluster building

For AWS ECR (Elastic Container Registry), you need to enable the ECR credential helper once for the repository by adding an `imagePullSecret` for you ECR repository.

First create a `config.json` somewhere with the following contents (`<aws_account_id>` and `<region>` are placeholders that you need to replace for your repo):

```json
{
  "credHelpers": {
    "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login"
  }
}
```

Next create the *imagePullSecret* in your cluster (feel free to replace the default namespace, just make sure it's correctly referenced in the config below):

```sh
kubectl --namespace default create secret generic ecr-config \
  --from-file=.dockerconfigjson=./config.json \
  --type=kubernetes.io/dockerconfigjson
```

Make note of the ImagePullSecret name and namespace.

### Configuring Access

To grant your service account the right permission to push to ECR, add this policy to each of the repositories in the container registry that you want to use with in-cluster building:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPushPull",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<account-id>:role/<k8s_worker_iam_role>"                ]
            },
            "Action": [
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:CompleteLayerUpload",
                "ecr:GetDownloadUrlForLayer",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage",
                "ecr:UploadLayerPart"
            ]
        }
    ]
}
```

To grant developers permission to push and pull directly from a repository, see [the AWS documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/security_iam_id-based-policy-examples.html).


# GCP

## Setting up a GCR registry

Follow [this guide](https://cloud.google.com/container-registry/docs/quickstart) to create a private GCR registry on GCP.

Then follow [this guide](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) to create an image pull secret so that your cluster can pull images from your registry.

Make note of the ImagePullSecret name and namespace.

## Enabling in-cluster building with GCR

To use in-cluster building with GCR (Google Container Registry) you need to set up authentication, with the following steps:

1. Create a Google Service Account (GSA).
2. Give the GSA the appropriate permissions.
3. Create a JSON key for the account.
4. Create an *imagePullSecret* for using the JSON key.
5. Add a reference to the imagePullSecret in your Garden project configuration.

First, create a Google Service Account:

```sh
# You can replace the gcr-access name of course, but make sure you also replace it in the commands below
gcloud iam service-accounts create gcr-access --project ${PROJECT_ID}
```

Then, to grant the Google Service account the right permission to push to GCR, run the following gcloud commands:

```sh
# Create a role with the required permissions
gcloud iam roles create gcrAccess \
  --project ${PROJECT_ID} \
  --permissions=storage.objects.get,storage.objects.create,storage.objects.list,storage.objects.update,storage.objects.delete,storage.buckets.create,storage.buckets.get

# Attach the role to the newly create Google Service Account
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member=serviceAccount:gcr-access@${PROJECT_ID}.iam.gserviceaccount.com \
  --role=projects/${PROJECT_ID}/roles/gcrAccess
```

Next create a JSON key file for the GSA:

```sh
gcloud iam service-accounts keys create keyfile.json --iam-account gcr-access@${PROJECT_ID}.iam.gserviceaccount.com
```

Then prepare the *imagePullSecret* in your Kubernetes cluster. Run the following command, if appropriate replacing `gcr.io` with the correct registry hostname (e.g. `index.docker.io` or `asia.gcr.io`):

```sh
kubectl --namespace default create secret docker-registry regcred \
  --docker-server=gcr.io \
  --docker-username=_json_key \
  --docker-password="$(cat keyfile.json)"
```

Finally, make note of the ImagePullSecret name and namespace.

## Enabling in-cluster building with Google Artifact Registry

To use in-cluster building with Google Artifact Registry you need to set up authentication, with the following steps:

1. Create a Google Service Account (GSA).
2. Give the GSA the appropriate permissions.
3. Create a JSON key for the account.
4. Create an *imagePullSecret* for using the JSON key.
5. Add a reference to the imagePullSecret to your Garden project configuration.

First, create a Google Service Account:

```sh
# Of course you can replace the gar-access name, but make sure you also replace it in the commands below.
gcloud iam service-accounts create gar-access --project ${PROJECT_ID}
```

The service account needs write access to the Google Artifacts Registry. You can either grant write access to all repositories with an IAM policy, or you can grant repository-specific permissions to selected repositories. We recommend the latter, as it follows the pattern of granting the least-privileged access needed.

To grant access to all Google Artifact Registries, run:

```sh
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member=serviceAccount:gar-access@${PROJECT_ID}.iam.gserviceaccount.com \
  --role=roles/artifactregistry.writer
```

To grant access to one or more repositories, run for each repository:

```sh
gcloud artifacts repositories add-iam-policy-binding ${REPOSITORY} \
  --location=${REGION} \
  --member=serviceAccount:gar-access@${PROJECT_ID}.iam.gserviceaccount.com \
  --role=roles/artifactregistry.writer
```

Next create a JSON key file for the GSA:

```sh
gcloud iam service-accounts keys create keyfile.json --iam-account gar-access@${PROJECT_ID}.iam.gserviceaccount.com
```

Then prepare the *imagePullSecret* in your Kubernetes cluster. Run the following command and replace `docker.pkg.dev` with the correct registry hostname (e.g. `southamerica-east1-docker.pkg.dev` or `australia-southeast1-docker.pkg.dev`):

```sh
kubectl --namespace default create secret docker-registry gar-config \
  --docker-server=docker.pkg.dev \
  --docker-username=_json_key \
  --docker-password="$(cat keyfile.json)"
```

Finally, make note of the ImagePullSecret name and namespace.


# Azure

## Setting up a registry

Follow [this guide](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal?tabs=azure-cli) to create a private Azure container registry on Azure portal.

Then follow [this guide](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-auth-kubernetes) to create an image pull secret so that your cluster can pull images from your registry.

Make note of the ImagePullSecret name and namespace.


# Docker Hub

To pull and push images from private Docker Hub repositories you need to create an image pull secret for Docker Hub. Creating an image pull secret for Docker Hub also reduces the chance of being [rate limited](/misc/faq#how-do-i-avoid-being-rate-limited-by-docker-hub) (e.g. when deploying Garden utility images).

{% hint style="info" %}
For a more in-depth guide on creating image pull secrets, check out the [official Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).
{% endhint %}

### Step 1 — Log in

Log in to the Docker Hub account you want to use with:

```sh
docker login
```

The login process creates or updates a `config.json` file that holds an authorization token. You can view it with:

```sh
cat ~/.docker/config.json
```

The output contains a section similar to this:

```json
{
    "auths": {
        "https://index.docker.io/v1/": {
            "auth": "c3R...zE2"
        }
    }
}
```

### Step 2 — Create the secret

You can now create the image pull secret with the following command:

```
kubectl create secret generic regcred \
    --from-file=.dockerconfigjson=<path/to/.docker/config.json> \
    --type=kubernetes.io/dockerconfigjson
```

Here we're creating a secret called `regcred` in the `default` namespace. Take note of the name and namespace as you'll need it when configuring the Kubernetes provider in [step 4](broken://pages/mOvjxDNRBznn2qwBLpWe).


# 3. Set Up Ingress, TLS and DNS

By default, Garden will not install an ingress controller for remote environments. This can be toggled by setting the [`setupIngressController` flag](/reference/providers/kubernetes#providerssetupingresscontroller) to `traefik` or `nginx`. Alternatively, you can set up your own ingress controller, e.g. using [Ambassador](https://www.getambassador.io/) or [Istio](https://istio.io/). You can find an example for [using Garden with Istio](https://github.com/garden-io/garden/tree/0.14.20/examples/istio) in our [examples directory](https://github.com/garden-io/garden/tree/0.14.20/examples).

{% hint style="warning" %}
The bundled nginx ingress controller is deprecated and will be removed in a future release. We recommend switching to Traefik by running `garden plugins kubernetes migrate-ingress-controller` and setting `setupIngressController: "traefik"` in your provider config.
{% endhint %}

You'll also need to point one or more DNS entries to your cluster, and configure a TLS certificate for the hostnames you will expose for ingress.

Templating the ingress to the application enables you to have DNS entries for every developer's namespace.

First, you will make DNS CNAME entry that points to the load balancer in front of your cluster. We recommend setting a wildcard in front of the proper record, e.g. \*...com.

If you would like to manage TLS for development environments, we recommend using your cloud provider's certificate management service in combination with a load balancer. You can find the documentation for [AWS here](https://aws.amazon.com/premiumsupport/knowledge-center/associate-acm-certificate-alb-nlb/) and for [GCP here](https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs).

If you are manually creating or obtaining the certificates (and you have the `.crt` and `.key` files), create a [Secret](https://kubernetes.io/docs/concepts/configuration/secret/) for each cert in the cluster so they can be referenced when deploying services:

```sh
kubectl create secret tls mydomain-tls-secret --key <path-to-key-file> --cert <path-to-crt-file>
```

Once you have completed the set up, make note of hostname.

If you're storing certs as Kubernetes Secrets, also make note of their names and namespaces.


# 4. Configure the Provider

Once you've completed steps 1-3 on the previous pages you should have all the values at hand to configure Garden's Kubernetes plugin.

In particular, you should have:

* The context for your Kubernetes cluster ([see step\
  1](/tutorials/remote-k8s/create-cluster)).
* The name(s) and namespace(s) of the ImagePullSecret(s) used by your cluster ([see step 2](/tutorials/remote-k8s/configure-registry)).
* The hostname for your services ([see step 3](/tutorials/remote-k8s/ingress-and-dns)).
* A TLS secret (optional) ([see step 3](/tutorials/remote-k8s/ingress-and-dns)).

Now we can finally add them to our Garden config.

## 1. Add initial config

First, add your values to the project level Garden configuration file at the root of your project:

```yaml
apiVersion: garden.io/v2
kind: Project

environments:
  - name: remote
    variables:
      hostname: <THE HOSTNAME FROM STEP 3>

providers:
  - name: kubernetes
    environments: [remote]
    imagePullSecrets: # You can set multiple secrets here
      - name: <THE IMAGE PULL SECRET FROM STEP 2>
        namespace: <THE IMAGE PULL SECRET NAMESPACE FROM STEP 2>
    deploymentRegistry:
      hostname: <THE REGISTRY HOSTNAME CONFIGURED IN STEP 2>
      namespace: <THE REGISTRY NAMESPACE CONFIGURED IN STEP 2>
    context: <THE KUBE CONTEXT FROM STEP 1>
    defaultHostname: <THE HOSTNAME FROM STEP 3>
```

{% hint style="warning" %}
Garden does NOT inject the image pull secret into the Deployment (unless you're using the `container` Deploy type). So if you're using e.g. the `kubernetes` or `helm` action types you need to make sure the `imagePullSecret` field is set in the corresponding manifest / Helm chart. See also the [official Kubernetes docs for setting image pull secrets](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-pod-that-uses-your-secret).
{% endhint %}

### 2. Select build mode

Next, select a "build mode".

You can choose between building your images locally with Docker using the `local-docker` build mode or remotely, in the cluster itself.

Note that even if you choose the `local-docker` build mode, you still need to configure a container registry that Garden can push to and set an ImagePullSecret so that Kubernetes can pull your images.

In general, we recommend doing remote building with the `cluster-buildkit` build mode.

This means you don't need Docker running on your laptop and you're able to share build caches with your team and across environments.

To use the `cluster-buildkit` build mode, add the following to your configuration:

```yaml
providers:
  - name: kubernetes
    buildMode: "cluster-buildkit" # <--- Add this
    # ...
```

### 3. Initialize the plugin

Finally, initialize the plugin by running:

```
garden plugins kubernetes cluster-init
```

And that's it! Your Kubernetes plugin is now configured\
and you can proceed to deploying your project to\
Kubernetes with Garden.

Next, we recommend learning more about configuring [Kubernetes actions](/using-garden-with/kubernetes).


# Containers

Garden can build your container images and the built image can then be referenced in your [Kubernetes manifests](/using-garden-with/kubernetes/deploy-k8s-resource), [Helm charts](/using-garden-with/kubernetes/install-helm-chart), and [tests runs](/using-garden-with/kubernetes/run-tests-and-tasks).

By default, Garden will use local Docker to build images but we highly recommend using our [Remote Container Builder](/using-garden-with/containers/using-remote-container-builder) which can significantly speed up your container builds (see link for how to set up).

You can then [add `container` Build actions](/using-garden-with/containers/building-containers) to your project that will be built via the appropriate build mode.


# Using Remote Container Builder

The [Remote Container Builder](/features/remote-container-builder) enables you to build container images using **blazing-fast, remote build compute instances** managed by Garden and to share build caches with your team.

Our free-tier includes a certain amount of build minutes and layer caching per month and you get more by switching to our team or enterprise tiers. You can learn more about the [different tiers here](https://app.garden.io/plans).

If you run out of build minutes, Garden will simply fallback to local builds without any disruption.

### Enabling Remote Container Builder

#### Step 1 — Log in to Garden Cloud

You need to be logged into Garden Cloud to use the remote container builder:

```sh
garden login
```

If this is your first time logging in, you'll be asked to sign up.

#### Step 2 — Configure the `container` provider (optional)

The Remote Container Builder is enabled by default once you've logged in, so no further configuration is required.

If you want more granular control and e.g. only enable the container builder in certain environments you can do that via `container` provider in your project level configuration.

For example:

```yaml
kind: Project
name: my-project
environments:
  - name: local
  - name: remote-dev
  - name: ci

providers:
  - name: container # <--- We configure the container builder under the `container` provider
    environments: [remote-dev, ci] # <-- Here we specify what environments in should be enabled in
    gardenContainerBuilder:
      enabled: true
  - name: kubernetes
    # ...
```

#### Step 3 — Give it a spin (optional)

If you a already have a Garden project with `container` Build actions, simply run:

```
garden build
```

...or any other command that triggers a build.

If you're using the `kubernetes` provider, the image will be pushed to the configured `deploymentRegistry`.

You can then check out the results in the [new Builds UI](https://app.garden.io).

### Known Limitations

#### Base images from other Build actions require a remote registry

When one Build action uses another Build action's output as a base image (via a `FROM` instruction referencing a build arg), a remote container registry must be configured for the Remote Container Builder to work.

For example, given a config like this:

```yaml
kind: Build
type: container
name: main
dependencies: [build.base]
spec:
  dockerfile: main.Dockerfile
  buildArgs:
    BASE_IMAGE: ${actions.build.base.outputs.deploymentImageId}
```

Where `main.Dockerfile` contains:

```dockerfile
ARG BASE_IMAGE
FROM $BASE_IMAGE
```

The Remote Container Builder will build the `base` image remotely and download it to your local Docker daemon. However, when it then builds `main`, the remote builder cannot resolve the `base` image because it only exists locally—not in any registry the remote builder can pull from.

Without a registry, the build will fail with an error like:

```
failed to resolve source metadata for docker.io/library/base:v-<hash>: not found
```

**Workaround:** Configure a `deploymentRegistry` in your `kubernetes` provider so that built images are pushed to a registry that the remote builder can access. Alternatively, you can disable the Remote Container Builder for environments that use this pattern.

### Next steps

If you haven't already, check out our docs on [building containers](/using-garden-with/containers/building-containers) to learn how to add `container` Build actions to your project. Note that the Remote Container Builder also supports [multi-platform builds](/using-garden-with/containers/building-containers#doing-multi-platform-builds)!

Your `container` actions will be built by the container builder and can be used by other actions, e.g. to:

* [Deploy K8s resources](/using-garden-with/kubernetes/deploy-k8s-resource)
* [Install Helm charts](/using-garden-with/kubernetes/install-helm-chart)
* [Run tests](/using-garden-with/kubernetes/run-tests-and-tasks)


# Building Containers

You can build containers with the `container` Build action:

```yaml
kind: Build
name: api
type: container
```

Most commonly you'll then want to deploy this image or use it in Test or Run actions. You can do that by referencing the output from the build in your Deploy actions via the `${actions.build.outputs.api.<output-name>}` template string.

For example, to deploy this image with Helm you can use the following config:

```yaml
kind: Deploy
name: api
type: helm
dependencies: [build.api] # <--- We need to specify the dependency here
spec:
  values:
    repository: ${actions.build.api.outputs.deploymentImageName}
    tag: ${actions.build.api.version}
```

Or you can set it in your Kubernetes manifests with the `patchResources` field:

```yaml

kind: Deploy
type: kubernetes
name: api
dependencies: [build.api] # <--- We need to specify the dependency here
spec:
  manifestFiles: [my-manifests.yml]
  patchResources:
    - name: api # <--- The name of the resource to patch, should match the name in the K8s manifest
      kind: Deployment # <--- The kind of the resource to patch
      patch:
        spec:
          template:
            spec:
              containers:
                - name: api # <--- Should match the container name from the K8s manifest
                  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action
```

You can learn more in the individual guides for the Kubernetes [Deploy](/using-garden-with/kubernetes/deploy-k8s-resource) and [Run and Test](/using-garden-with/kubernetes/run-tests-and-tasks) actions.

### Examples

#### Building images

Following is a bare minimum `Build` action using the `container` type:

```yaml
# garden.yml
kind: Build
type: container
name: my-container
```

If you have a `Dockerfile` in the same directory as this file, this is enough to tell Garden to build it. However, you can override the `Dockerfile` name or path by specifying `spec.dockerfile: <path-to-Dockerfile>`. You might also want to explicitly [include or exclude](/guides/include-exclude) files in the build context.

#### Setting build arguments

You can specify [build arguments](https://docs.docker.com/engine/reference/commandline/build/#build-arg) using the [`spec.buildArgs`](/reference/action-types/build/container#specbuildargs) field. This can be quite handy, especially when e.g. referencing other `Build` action as build dependencies:

```yaml
# garden.yml
kind: Build
type: container
name: my-container
# Here, we ensure that the base image is built first. This is useful e.g. when you want to build a prod and a
# dev/testing variant of the image in your pipeline.
dependencies: [ build.base-image ]
spec:
  buildArgs:
    baseImageVersion: ${actions.build.base-image.version}
```

{% hint style="warning" %}
When using the Remote Container Builder, builds that reference other Build actions as base images (via build args used in `FROM` instructions) require a remote container registry to be configured. Without one, the remote builder cannot resolve the locally-built base image. See [Known Limitations](/using-garden-with/containers/using-remote-container-builder#known-limitations) for details.
{% endhint %}

Additionally, Garden automatically sets `GARDEN_ACTION_VERSION` as a build argument, which you can use to reference the version of action being built. You use it internally as a [Docker buildArg](https://docs.docker.com/engine/reference/commandline/build/#build-arg). For instance, to set versions, render docs, or clear caches.

#### Using remote images

If you're not building the container image yourself and just need to deploy an image that already exists in a registry, you need to specify the `image` in the `Deploy` action's `spec`:

```yaml
# garden.yml
kind: Deploy
type: container
name: redis
spec:
  image: redis:5.0.5-alpine   # <- replace with any docker image ID
```

#### Doing multi-platform builds

Garden supports building container images for multiple platforms and architectures. Use the `platforms` configuration field, to configure the platforms you want to build for e.g.:

```yaml
# garden.yml
kind: Build
type: container
name: my-container
spec:
  platforms: ["linux/amd64", "linux/arm64"]
```

Garden interacts with several local and remote builders. Currently support for multi-platform builds varies based on the builder backend. The following build backends support multi-platform builds out of the box: [Garden Container Builder](/reference/providers/container), `cluster-buildkit`, `kaniko`.

In-cluster building with `kaniko` does *not* support multi-platform builds.

The `local-docker` build backend requires some additional configurations. Docker Desktop users can enable the experimental containerd image store to also store multi-platform images locally. All other local docker solutions e.g. orbstack, podman currently need a custom buildx builder of type `docker-container`. Documemtation for both can be found here <https://docs.docker.com/build/building/multi-platform>. If your local docker image store does not support storing multi-platform images, consider configuring an environment where you only build single platform images when building locally e.g.:

```yaml
# garden.yml
kind: Build
type: container
name: my-container
spec:
  platforms:
    $if: ${environment.name == "local"}
    $then: [ "linux/amd64"]
    $else: [ "linux/amd64", "linux/arm64" ]
```

Or you can specifiy to push your locally build images to a remote registry. If you are also using a Kubernetes provider and have a `deploymentRegistry` defined, the image will be pushed to this registry by default. If you are using garden only for building with the container provider, you can achieve the same behavior by specifying `--push` as an extra flag in your container action and setting `localId` to your registry name.

#### Publishing images

You can publish images that have been built in your cluster using the `garden publish` command.

Unless you're publishing to your configured deployment registry (when using the `kubernetes` provider), you need to specify the `publishId` field on the `container` action's `spec` in question to indicate where the image should be published. For example:

```yaml
kind: Build
name: my-build
type: container
spec:
  publishId: my-repo/my-image:v1.2.3   # <- if you omit the tag here, the Garden action version will be used by default
```

By default, we use the tag specified in the `container` action's `spec.publishId` field. If none is set, we default to the corresponding `Build` action's version.

You can also set the `--tag` option on the `garden publish` command to override the tag used for images. You can both set a specific tag or you can *use template strings for the tag*. For example, you can

* Set a specific tag on all published builds: `garden publish --tag "v1.2.3"`
* Set a custom prefix on tags but include the Garden version hash: `garden publish --tag 'v0.1-${build.hash}'`
* Set a custom prefix on tags with the current git branch: `garden publish --tag 'v0.1-${git.branch}'`

{% hint style="warning" %}
Note that you most likely need to wrap templated tags with single quotes, to prevent your shell from attempting to perform its own substitution.
{% endhint %}

Generally, you can use any template strings available for action configs for the tags, with the addition of the following:

* `${build.name}` — the name of the build being tagged
* `${build.version}` — the full Garden version of the build being tagged, e.g. `v-abcdef1234`
* `${build.hash}` — the Garden version hash of the build being tagged, e.g. `abcdef1234` (i.e. without the `v-` prefix)


# Kubernetes

You can use Garden with a local or a remote Kubernetes cluster. First you need to tell Garden how to connect to your cluster by following either of these guides:

* [Using remote Kubernetes](/using-garden-with/kubernetes/remote-kubernetes)
* [Using local Kubernetes](/using-garden-with/kubernetes/local-kubernetes)

You can then add actions for deploying K8s resources, installing Helm charts, running tests and more. Below is a overview of the actions with links to more resources:

* [The `kubernetes` Deploy action](/using-garden-with/kubernetes/deploy-k8s-resource) – Use this action if you already have Kubernetes manifests for some of the workloads you want to deploy and/or if you're using Kustomize.
* [The `helm` Deploy action](/using-garden-with/kubernetes/install-helm-chart)—Use this action if you're using Helm and have the corresponding Helm charts.
* [The `kubernetes-pod` Test/Run action](/using-garden-with/kubernetes/run-tests-and-tasks) – Use this if you already have the corresponding Kubernetes manifests and want to run the test/run command in a dedicated Pod that gets cleaned up after the run.
* [The `kubernetes-pod` Test/Run action](/using-garden-with/kubernetes/run-tests-and-tasks) – Use this action for running tests/tasks if you already have Kubernetes manifests and want to run the test/run command in an already deployed Kubernetes Pod. This is faster than (potentially) waiting for an image build and for a new Pod being created and is a good choice for e.g. running tests while iterating during development.
* [The `kubernetes-pod` Test/Run action](/using-garden-with/kubernetes/run-tests-and-tasks) – Use this action for running test/tasks if you have the corresponding Helm charts.

### How it works

Under the hood, Garden uses the Kubernetes API and kubectl to interact with your Kubernetes cluster.

Typically, each developer will have their own isolated Kubernetes Namespace. Similarly, CI tests and preview environments are isolated via Namespaces, although this is all configurable.

For tests and tasks, Garden spins up Pods from the respective image that execute the task.

For live code synchronization, Garden uses a tool called Mutagen to sync changes to the running container.

There's a lot more to the Kubernetes plugins and if you're interested in the "nitty-gritty", we're more than happy to answer questions us on [Garden Discussions](https://github.com/garden-io/garden/discussions).


# Using Remote Kubernetes

### Requirements

To use Garden to deploy to and test in a remote Kubernetes cluster you'll need to configure the `kubernetes` provider. This requires:

* A Kubernetes cluster (obviously).
* Permissions to create Namespaces and to create Deployments, Daemonsets, Services and Ingresses within the Namespaces created.
* A container registry that Garden can push images to and that your cluster can pull images from.
* Ingress and DNS set up.

You can follow our [step-by-step Kubernetes tutorial](/tutorials/remote-k8s) for setting these up if you haven't done so already. In general there are a lot of ways to create these resources so feel free to use whatever approach you find most useful.

In any case, you'll need the following values at hand to configure the provider:

* The context for your Kubernetes cluster ([see tutorial step 1](/tutorials/remote-k8s/create-cluster)).
* The name(s) and namespace(s) of the ImagePullSecret(s) used by your cluster ([see tutorial step 2](/tutorials/remote-k8s/configure-registry)).
* The hostname for your services ([see tutorial step 3](/tutorials/remote-k8s/ingress-and-dns)).
* A TLS secret (optional) ([see tutorial step 3](/tutorials/remote-k8s/ingress-and-dns)).

### Provider configuration

When you have these values you can configure the `kubernetes` provider like so:

```yaml
apiVersion: garden.io/v2
kind: Project

environments:
  - name: remote

providers:
  - name: kubernetes
    environments: [remote]
    imagePullSecrets:
      - name: <THE IMAGE PULL SECRET FROM TUTORIAL STEP 2>
        namespace: <THE IMAGE PULL SECRET NAMESPACE FROM TUTORIAL STEP 2>
    deploymentRegistry:
      hostname: <THE REGISTRY HOSTNAME CONFIGURED IN TUTORIAL STEP 2>
      namespace: <THE REGISTRY NAMESPACE CONFIGURED INTUTORIAL  STEP 2>
    context: <THE KUBE CONTEXT FROM TUTORIAL  STEP 1>
    buildMode: cluster-buildkit
    defaultHostname: <THE HOSTNAME FROM TUTORIAL STEP 3>
```

Once you have this configured you can start adding actions for deploying K8s resources, installing Helm charts, running tests, and more in your remote cluster.


# Using Local Kubernetes

### Requirements

To use Garden to deploy to and test in a local Kubernetes cluster like Minikube or k3s you'll need one installed. If you don't have one check out our [guide on installing local Kubernetes](/guides/install-local-kubernetes).

### Provider configuration

The `local-kubernetes` provider attempts to automatically detect which flavor of local Kubernetes is installed, and set the appropriate context for connecting to the local Kubernetes instance. So the only configuration you need is this:

```yaml
# In project.garden.yml
apiVersion: garden.io/v2
kind: Project
environments:
  - name: local
providers:
  - name: local-kubernetes
    environments: [local]
```

If you happen to have installed both Minikube and a version of Docker for Mac with Kubernetes support enabled, `garden` will choose whichever one is configured as the current context in your `kubectl` configuration. If neither is set as the current context, the first available context is used.

You can always override this by configuring it explicitly in your project-level config as follows:

```yaml
providers:
  - name: local-kubernetes
    environments: [local]
    context: minikube # <--- Explicitly set the context
```

Now you can start adding actions for deploying K8s resources, installing Helm charts, running tests, and more in your local cluster.


# Deploying K8s Resources

{% hint style="info" %}
To use Garden to deploy a K8s resource you need to configure the [remote](/using-garden-with/kubernetes/remote-kubernetes) or [local](/using-garden-with/kubernetes/local-kubernetes) Kubernetes providers.
{% endhint %}

You can deploy Kubernetes resources with the `kubernetes` Deploy action.

In the sections below we'll explain how to:

* Point Garden to your manifests
* Deploy a container image that's been built by Garden
* Overwrite values in your manifests to suit your environment
* Set the deployment target so Garden can stream logs and sync code changes
* Configure code syncing for rapid development

The `kubernetes` Deploy action works very similarly to the [`helm`](/using-garden-with/kubernetes/install-helm-chart) Deploy action, and you'll find a lot common between the two guides.

See the full spec for the `kubernetes` deploy action in our [reference docs](/reference/action-types/deploy/kubernetes).

### Referencing manifests

When configuring a `kubernetes` Deploy action, you point Garden to the manifest files via the `spec.files` directive.

You can also specify them inline in your Garden config via the `spec.manifests` field but we recommend the former approach since that allows you to re-use them with other tools.

#### Option 1: Manifest files (recommended)

If your project structure looks something like this:

```console
.
├── api
│   ├── garden.yml
│   ├── manifests
│   │   ├── prod
│   │   ├── Deployment.yaml
│   │   ├── Ingress.yaml
│   │   └── Service.yaml
│   │   ├── dev
│   │   ├── Deployment.yaml
│   │   ├── Ingress.yaml
│   │   └── Service.yaml
│   └── src
└── project.garden.yml
```

You can reference the manifests like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles:
    - ./manifests/Deployment.yaml
    - ./manifests/Ingress.yaml
    - ./manifests/Service.yaml
```

You can also use glob patterns like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles:
    - ./manifests/*
```

You can also use templating to reference different manifests based on environment.

For example, if your project structure looks like this:

```console
.
├── api
│   ├── garden.yml
│   ├── manifests
│   │   ├── dev
│   │   │   ├── Deployment.yaml
│   │   │   ├── Ingress.yaml
│   │   │   └── Service.yaml
│   │   └── prod
│   │       ├── Deployment.yaml
│   │       ├── Ingress.yaml
│   │       └── Service.yaml
│   └── src
└── project.garden.yml
```

You can reference the manifests like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles:
    - ./manifests/${environment.name}/Deployment.yaml
    - ./manifests/${environment.name}/Ingress.yaml
    - ./manifests/${environment.name}/Service.yaml
```

If your manifests are in a parent directory relative to the action config file, you need to set the `source.path` field for your action since Garden cannot include files from parent directories.

For example, if your project has the following structure:

```console
.
├── api
│   ├── src
│   ├── garden.yml
├── manifests
│   ├── Deploment.yaml
│   ├── Ingress.yaml
│   └── Service.yaml
└── project.garden.yml
```

You can reference manifests like so:

```yaml
kind: Deploy
type: kubernetes
name: api
source:
  path: ../ # <--- Garden will now treat the parent directory as the action source path
spec:
  manifestFiles:
    - ./manifests/Deployment.yaml # <--- Reference the manifests relative to the source path
    - ./manifests/Ingress.yaml
    - ./manifests/Service.yaml
```

#### Option 2: Inline

You can also include the manifests inline with your Garden configuration although we generally recommend having dedicated manifest files since those are easier to re-use and will work with other tools.

You define manifests inline like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifests:
    - apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: api
        labels:
          app: api
      spec:
        # ...

    - apiVersion: v1
      kind: Service
      metadata:
      labels:
        app: api
        name: api
      spec:
        # ...
    - apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: api
        labels:
          app: api
      spec:
        # ...
```

### Deploying a container image built by Garden

Most commonly you'll use the `kubernetes` Deploy action together with a `container` Build action. That is, you build your source code with one action and deploy it with another.

Simplified, it looks like this:

```yaml
kind: Build
type: container
name: api
---
kind: Deploy
type: kubernetes
name: api
dependencies: [build.api] # <--- This ensures the image is built before its deployed
spec:
  manifestFiles: [my-manifests.yml]
```

The problem here is that your manifests will likely contain a "hard coded" container image whereas the image built by Garden will have a different version.

There's a few ways to handle that but the recommend approach is to use the `patchResources` field.

#### Option 1: Patching resources (recommended)

The `patchResources` directive allows you to overwrite any field in your manifests using [Kubernetes' built-in patch functionality](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/) without modifying the underlying manifest.

The config will look like this:

```yaml
kind: Build
type: container
name: api
---
kind: Deploy
type: kubernetes
name: api
dependencies: [build.api]
spec:
  manifestFiles: [my-manifests.yml]
  patchResources:
    - name: api # <--- The name of the resource to patch, should match the name in the K8s manifest
      kind: Deployment # <--- The kind of the resource to patch
      patch:
        spec:
          template:
            spec:
              containers:
                - name: api # <--- Should match the container name from the K8s manifest
                  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action above
```

With this approach, you can add the Garden action to your project without making any changes to existing config.

Here's a [complete example project](https://github.com/garden-io/garden/tree/0.14.20/examples/k8s-deploy-patch-resources) using this approach.

#### Option 2: Using Garden template strings

You can use Garden template strings if you define your manifests inline:

```yaml
kind: Build
type: container
name: api
---
kind: Deploy
type: kubernetes
name: api
dependencies: [build.api]
spec:
  manifestFiles: [my-manifests.yml]
  manifests:
    - apiVersion: apps/v1
      kind: Deployment
      spec:
        template:
          spec:
            containers:
              - name: api
                image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action above
```

### Overwriting values

You can use the exact same pattern as above where we set the container image to overwrite other values from your manifests.

If you for example need to change the number or replicas depending on environment and/or set some env variables, you can do so via the `patchResources` field like we did above. For example:

```yaml
kind: Build
type: container
name: api
---
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles: [my-manifests.yml]
  patchResources:
    - name: api # <--- The name of the resource to patch, should match the name in the K8s manifest
      kind: Deployment # <--- The kind of the resource to patch
      patch:
        spec:
          replicas: "${environment.name == 'dev' ? 1 : 3}" # <--- Set replicas depending on environment
          template:
            spec:
              containers:
                - name: api # <--- Should match the container name from the K8s manifest
                  env:
                    LOG_LEVEL: "${environment.name == 'dev' ? 'verbose' : 'info' }"
```

The benefit of this approach is that you don't need to make any changes to your existing manifests.

Here's one more example where we iterate over a list of variables defined in Garden config and set them as environment variables for a given container:

```yaml
kind: Build
type: container
name: api
---
kind: Deploy
type: kubernetes
name: api

variables:
  apiEnv: # <--- Garden variables that we'll set as K8s container env vars
    DATABASE_PASSWORD: ${imported.DATABASE_PASSWORD} # <--- A secret variable stored in Garden Cloud
    NODE_ENV: development
    PORT: ${var.API_PORT} # <--- A shared variable that's set in the project config that we reference here

spec:
  manifestFiles: [my-manifests.yml]
  patchResources:
    - name: api
      kind: Deployment
      patch:
        spec:
          template:
            spec:
              containers:
                - name: api
                  env:
                    $forEach: ${var.apiEnv} # <--- Iterate over the values of ${var.apiEnv} variable...
                    $filter: "${item.value ? true : false}" # <--- ...optionally filter out empty values since Kubernetes doesn't support it...
                    $return: # <--- ...return them as valid Kubernetes name/value pairs
                      name: ${item.key}
                      value: ${string(item.value)}
```

If you'd rather use template strings in the manifests, you can do that as well as described in the [referencing container images](#option-2-using-garden-template-strings) section above.

### Setting a default target resource

{% hint style="info" %}
This is only relevant for Deploy actions that deploy resources that contain a Pod spec. If you're using the action to e.g. deploy a ConfigMap or a Secret you can skip this.
{% endhint %}

Some Garden commands like the `logs` and `exec` commands depend on Garden knowing what the target Kubernetes resource is. Same applies to code synchronization, Garden needs to know into what container in which Pod to sync code changes.

To enable this, users can configure a default target for Garden to use for these commands like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles: [my-manifests.yml]
  defaultTarget: # <--- The values below should match one of the K8s resources from the manifests
    kind: Deployment
    name: api
    containerName: api # <--- If not set, Garden picks the first container from the Pod spec
```

Instead of specifying the target kind and name, you can also set a pod selector directly like so:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles: [my-manifests.yml]
  defaultTarget:
    podSelector: # <--- This should match the labels in the desired Pod spec. A random Pod with matching labels will be picked as the target.
      app: api
      environment: dev
```

### Code Synchronization

Code synchronization (i.e. hot reloading) can be configured for the Kubernetes Deploy action. In the example below, code synchronization is set up from the `api` Build action's directory.

```yaml
kind: Deploy
type: kubernetes
name: api
---
spec:
  defaultTarget:
    kind: Deployment
    name: api
  sync:
    paths:
      - containerPath: /app/src
        sourcePath: ${actions.build.api.sourcePath}/src
        mode: two-way
```

For more information on synchronization, check out the full [Code Synchronization Guide](/features/code-synchronization).

### Production environments

You can define a remote environment as a `production` environment by setting the [production flag](/reference/project-config#environmentsproduction) to `true`. This affects some default behavior when working with `kubernetes` actions. See the [Deploying to production](/guides/deploying-to-production) guide for details.

### Next steps

Look into adding [Test and Run](/using-garden-with/kubernetes/run-tests-and-tasks) actions.

You'll also find the [full Kubernetes Deploy action reference here](/reference/action-types).


# Installing Helm charts

{% hint style="info" %}
To use Garden to install Helm charts you need to configure the [remote](/using-garden-with/kubernetes/remote-kubernetes) or [local](/using-garden-with/kubernetes/local-kubernetes) Kubernetes providers.
{% endhint %}

The [Helm](https://helm.sh/) package manager is one of the most commonly used tools for managing Kubernetes manifests. Garden supports using your own Helm charts, alongside your container builds, via the `kubernetes` and `local-kubernetes` providers. This guide shows you how to configure and use 3rd-party (or otherwise external) Helm charts, as well as your own charts in your Garden project. We also go through how to set up tests, runs and code synchronization for your charts.

In this guide we'll be using the [vote-helm](https://github.com/garden-io/garden/blob/latest-release/examples/vote-helm/README.md) project. If you prefer to just check out a complete example, the project itself is also a good resource.

You may also want to have a look at the reference documentation for the helm [`deploy`](/reference/action-types/deploy/helm) action type.[`helm-pod` run](/reference/action-types/run/helm-pod), [`helm-pod` test](/reference/action-types/test/helm-pod) and[`kubernetes-exec`](/reference/action-types/run/kubernetes-exec) actions can be used for testing and task purposes.

*Note: If you only need a way to deploy some Kubernetes manifests and don't need all the features of Helm, you canuse the simpler `kubernetes` action instead. Check out the*[*kubernetes guide*](/using-garden-with/kubernetes/deploy-k8s-resource) *for more info.*

### Referencing external charts

Using external charts, where the chart sources are not located in your own project, can be quite straightforward. At a\
minimum, you just need to point to the chart, and perhaps provide some values as inputs. There are two options to deploy external Charts, [Helm chart repositories](https://helm.sh/docs/topics/chart_repository/) (Accessible via `https`) or [OCI-based registries](https://helm.sh/docs/topics/registries/).

#### Example: Redis from Bitnami OCI Repository

A specific chart repository can be referenced via the `repo` field. This may be useful if you run your own Helm Chart Repository for your organization, or are referencing an action that isn't contained in the default Helm Repository.

```yaml
kind: Deploy
type: helm
name: redis
spec:
  chart:
    # Chart name is part of the OCI URL
    url: oci://registry-1.docker.io/bitnamicharts/redis
    version: "19.0.1"
  values:
    auth:
      enabled: false
```

#### Example: Redis from Bitnami Helm Repository

A specific chart repository can be referenced via the `repo` field. This may be useful if you run your own Helm Chart Repository for your organization, or are referencing an action that isn't contained in the default Helm Repository.

```yaml
kind: Deploy
type: helm
name: redis
spec:
  chart:
    name: redis
    repo: https://charts.bitnami.com/bitnami
    version: "16.13.1"
  values:
    auth:
      enabled: false
```

### Local charts

Instead of fetching the chart sources from another repository, you'll often want to include your chart sources in your Garden project. To do this, you can simply add a `garden.yml` in your chart directory (next to your `Chart.yaml`) and start by giving it a name:

```yaml
kind: Deploy
description: My helm deploy action
type: helm
name: helm-deploy
```

You can also use Garden's external repository support, to reference chart sources in another repo:

```yaml
kind: Deploy
description: My helm deploy action
type: helm
name: helm-deploy
source:
  repository:
    url: https://github.com/my-org/my-helm-chart#v0.1
```

### `helm-pod` runs and tests

For tasks and tests either the `helm-pod` or `kubernetes-exec` actions can be used.

[`helm-pod` run](/reference/action-types/run/helm-pod) and [`helm-pod` test](/reference/action-types/test/helm-pod) actions will create a fresh kubernetes workload and run your command in it. These actions are cached. This means that if garden will not rerun them if the version of the action hasn't changed. If a remote kubernetes cluster is used, test results are stored there which allows to share test results between the team or ci runs to decrease the number or re-runs.

`helm-pod` actions don't have to depend on the deploy actions. The manifests are gathered from the rendered helm charts and deployed to the cluster.

Here's a test action from the [vote-helm example](https://github.com/garden-io/garden/blob/latest-release/examples/vote-helm/vote/garden.yml).

```yaml
kind: Test
name: vote-integ-pod
type: helm-pod
dependencies:
  - deploy.api
variables:
  hostname: vote.${var.baseHostname}
timeout: 60
spec:
  resource:
    kind: Deployment
    name: vote-integ-pod
  command: [/bin/sh, -c, "npm run test:integ"]
  values:
...
```

### Providing values to the Helm chart

In most cases you'll need to provide some parameters to the Helm chart you're using. The simplest way to do this is via the `spec.values`field:

```yaml
kind: Deploy
type: helm
name: helm-deploy
...
spec:
  values:
    some:
      key: some-value
```

This will effectively create a new YAML with the supplied values and pass it to Helm when rendering/deploying the chart. This is particularly handy when you want to template in the values (see the next section for a good example).

You can also provide you own value files, which will work much the same way. You just need to list the paths to them (relative to the action root,\
i.e. the directory containing the `garden.yml` file) and they will be supplied to Helm when rendering/deploying. For example:

```yaml
# garden.yml
kind: Deploy
type: helm
name: helm-deploy
...
spec:
  valueFiles:
    - values.default.yaml
    - values.${environment.name}.yaml
```

```yaml
# values.default.yaml
some:
  key: default-value
other:
  key: other-default
```

```yaml
# values.prod.yaml
some:
  key: prod-value
```

In this example, `some.key` is set to `"prod-value"` for the `prod` environment, and `other.key` maintains the default value set in `values.default.yaml`.

If you also set the `values` field in the Action configuration, the values there take precedence over both of the value files.

### Linking container builds and Helm deploy actions

When your project also contains one or more `container` build actions that build the images used by a `helm` deploy,\
you want to make sure the containers are built ahead of deploying the Helm chart, and that the correct image tag is used when deploying.\
The `vote-helm/worker` deploy and the corresponding `worker-image` build provide a simple example:

```yaml
kind: Build
type: container
name: worker-image

```

```yaml
kind: Deploy
description: Helm deploy for the worker container
type: helm
name: worker-deploy
dependencies: [build.worker-image]
spec:
  values:
    image:
      repository: ${actions.build.worker-image.outputs.deployment-image-name}
      tag: ${actions.build.worker-image.version}

```

Here the `worker-deploy` injects the `worker-image` version into the Helm chart via the `spec.values` field.\
Note that the shape of the chart's `values.yaml` file will dictate how exactly you provide the image version/tag to the chart\
(this example is based on the default template generated by `helm create`), so be sure to consult the reference for the chart in question.

Notice that this can also work if you use multiple containers in a single chart. You just add them all as dependencies, and the appropriate reference under `values`.

### Code Synchronization

Synchronization can be configured with helm deploys. In the example below code synchronization is set up from the `vote-image` build action's directory.

```yaml
kind: Deploy
type: helm
name: vote
...
spec:
  defaultTarget:
    kind: Deployment
    name: vote
  sync:
    paths:
      - containerPath: /app/src
        sourcePath: ${actions.build.vote-image.sourcePath}/src
        mode: two-way

```

For more information on synchronization check out the [Code Synchronization Guide](/features/code-synchronization).

### Re-using charts

Often you'll want to re-use the same Helm charts for multiple actions. For example, you might have a generic template\
for all your backend services that configures auto-scaling, secrets/keys, sidecars, routing and so forth, and you don't\
want to repeat those configurations all over the place.

**TODO: allow non-relative paths for the chart and then write this**

### Production environments

You can define a remote environment as a `production` environment by setting the [production flag](/reference/project-config#environmentsproduction) to `true`. This affects some default behavior when working with `helm` actions. See the [Deploying to production](/guides/deploying-to-production) guide for details.

### Next steps

Check out the full [action reference](/reference/action-types) for more details\
and the [vote-helm](https://github.com/garden-io/garden/blob/latest-release/examples/vote-helm/README.md) example project for a full project\
that showcases Garden's Helm support.

Also check out the [Kubernetes action](/using-garden-with/kubernetes/deploy-k8s-resource) if you don't need all the features of Helm.


# Running Tests and Tasks

{% hint style="info" %}
To use Garden to run Kubernetes tests and tasks you need to configure the [remote](/using-garden-with/kubernetes/remote-kubernetes) or [local](/using-garden-with/kubernetes/local-kubernetes) Kubernetes providers.
{% endhint %}

### Tests

#### Container

The `container` Run and Test actions can be used for running one off jobs as a Pod using a given container image and similarly for running test. For example:

```yaml
kind: Build
name: api
type: container
---
kind: Test
name: api
type: container
dependencies: [build.api]
spec:
  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action
  command: [npm, run, test]
---
kind: Run
name: seed-db
type: container
dependencies: [build.api]
spec:
  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action
  command: [npm, run, seed-db]
```

#### Helm Pod

This action type can be used for Run and Test actions where you already have the corresponding Helm charts. It's similar to the `kubernetes-pod` action type.

See the [`helm-pod` Run](/reference/action-types/run/helm-pod) and [`helm-pod` Test](/reference/action-types/test/helm-pod) reference docs for more details.

#### Kubernetes Pod

For Run and Test actions, either the `kubernetes-pod` or `kubernetes-exec` actions can be used.

[`kubernetes-pod` Run](/reference/action-types/run/kubernetes-pod) and [`kubernetes-pod` test](/reference/action-types/test/kubernetes-pod) will create a fresh Kubernetes workload and run your command in it. These actions are cached. This means that Garden will not rerun them if the version of the action hasn't changed. If a remote Kubernetes cluster is used, test results are stored there which allows to share test results between the team or CI runs to decrease the number or re-runs.

`kubernetes-pod` actions don't have to depend on the deploy actions. The manifests are gathered from the kubernetes manifests and deployed to the cluster.

```yaml
kind: Test
name: vote-integ-pod
type: kubernetes-pod
dependencies:
  - deploy.api
variables:
  hostname: vote.${var.baseHostname}
timeout: 60
spec:
  resource:
    kind: Deployment
    name: vote-integ-pod
  command: [/bin/sh, -c, "npm run test:integ"]
  values:
...
```

#### Kubernetes Exec

[`kubernetes-exec` Run](/reference/action-types/run/kubernetes-exec) and[`kubernetes-exec` Test](/reference/action-types/test/kubernetes-exec) actions are used to execute a command in an already deployed\
Kubernetes Pod and wait for it to complete. These actions are not cached. They can be used with deploys running in sync mode\
for rapid testing and development. These actions should depend on the deploy action that creates the kubernetes workloads they run in.

Here's a run action from the [vote-helm example](https://github.com/garden-io/garden/blob/latest-release/examples/vote-helm/postgres/garden.yml)\
that initializes the database by running a command in the already deployed kubernetes workload.

```yaml
kind: Run
name: db-init
type: kubernetes-exec
dependencies: [deploy.db]
spec:
  resource:
    kind: "StatefulSet"
    name: "postgres"
  command:
    [
      "/bin/sh",
      "-c",
      "PGPASSWORD=postgres psql -w -U postgres --host=postgres --port=5432 -d postgres -c 'CREATE TABLE IF NOT EXISTS votes (id VARCHAR(255) NOT NULL UNIQUE, vote VARCHAR(255) NOT NULL, created_at timestamp default NULL)'",
    ]

```

#### Test Artifacts

Many action types, including `container`, `exec` and `helm`, allow you to extract artifacts after Tests have completed. This can be handy when you'd like to view reports or logs, or if you'd like a script (via a local `exec` action, for instance) to validate the output from a Test.

Desired artifacts can be specified using the `spec.artifacts` field on Test configurations. For example, for the `container` Test, you can do something like this:

```yaml
kind: Test
type: container
name: my-test
...
spec:
  command: [some, command]
  artifacts:
    - source: /report/*
      target: my-test-report
```

After running `my-test`, you can find the contents of the `report` directory in the test's container, locally under `.garden/artifacts/my-test-report`.

Please look at individual [action type references](/reference/action-types) to see how to configure each Run to extract artifacts.

### Tasks

#### Container

The `container` Run and Test actions can be used for running one off jobs as a Pod using a given container image and similarly for running test. For example:

```yaml
kind: Build
name: api
type: container
---
kind: Test
name: api
type: container
dependencies: [build.api]
spec:
  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action
  command: [npm, run, test]
---
kind: Run
name: seed-db
type: container
dependencies: [build.api]
spec:
  image: ${actions.build.api.outputs.deployment-image-id} # <--- The output from the Build action
  command: [npm, run, seed-db]
```

#### Helm Pod

This action can be used for Run and Test actions where you already have the corresponding Helm charts. It's similar to the `kubernetes-pod` action.

See the [`helm-pod` Run](/reference/action-types/run/helm-pod) and [`helm-pod` Test](/reference/action-types/test/helm-pod) reference docs for more details.

#### Kubernetes Pod

For Run and Test actions, either the `kubernetes-pod` or `kubernetes-exec` actions can be used.

[`kubernetes-pod` Run](/reference/action-types/run/kubernetes-pod) and [`kubernetes-pod` test](/reference/action-types/test/kubernetes-pod) will create a fresh Kubernetes workload and run your command in it. These actions are cached. This means that Garden will not rerun them if the version of the action hasn't changed. If a remote Kubernetes cluster is used, test results are stored there which allows to share test results between the team or CI runs to decrease the number or re-runs.

`kubernetes-pod` actions don't have to depend on the deploy actions. The manifests are gathered from the kubernetes manifests and deployed to the cluster.

```yaml
kind: Test
name: vote-integ-pod
type: kubernetes-pod
dependencies:
  - deploy.api
variables:
  hostname: vote.${var.baseHostname}
timeout: 60
spec:
  resource:
    kind: Deployment
    name: vote-integ-pod
  command: [/bin/sh, -c, "npm run test:integ"]
  values:
...
```

#### Kubernetes Exec

[`kubernetes-exec` Run](/reference/action-types/run/kubernetes-exec) and [`kubernetes-exec` Test](/reference/action-types/test/kubernetes-exec) actions are used to execute a command in an already deployed Kubernetes Pod and wait for it to complete. These actions are not cached. They can be used with deploys running in sync mode for rapid testing and development. These actions should depend on the deploy action that creates the kubernetes workloads they run in.

Here's a run action from the [vote-helm example](https://github.com/garden-io/garden/blob/latest-release/examples/vote-helm/postgres/garden.yml) that initializes the database by running a command in the already deployed kubernetes workload.

```yaml
kind: Run
name: db-init
type: kubernetes-exec
dependencies: [deploy.db]
spec:
  resource:
    kind: "StatefulSet"
    name: "postgres"
  command:
    [
      "/bin/sh",
      "-c",
      "PGPASSWORD=postgres psql -w -U postgres --host=postgres --port=5432 -d postgres -c 'CREATE TABLE IF NOT EXISTS votes (id VARCHAR(255) NOT NULL UNIQUE, vote VARCHAR(255) NOT NULL, created_at timestamp default NULL)'",
    ]

```


# Local Volume Mounts

{% hint style="warning" %}
This feature is **experimental** and its configuration format may change in future releases.
{% endhint %}

Garden can automatically inject host-directory volume mounts into your local Kubernetes workloads, mapping directories from your machine directly into running containers. This is an alternative to [code synchronization](/features/code-synchronization) that uses Kubernetes `hostPath` volumes instead of Mutagen-based file sync.

Local volume mounts are useful when you want:

* Instant file visibility with no sync delay
* Simple setup that works with any file watcher or hot-reload tool already in your container
* No background sync process to manage

The feature works with both `kubernetes` and `helm` Deploy actions.

### How it works

When you configure `localVolumes` on a Deploy action, Garden:

1. Resolves the `sourcePath` relative to the action's source directory into an absolute host path
2. Converts the host path to the correct format for your local cluster type and OS
3. Injects `hostPath` volumes and `volumeMounts` into the target workload's pod spec
4. Applies the modified manifests to the cluster
5. Verifies that the mounted files are visible inside the running pod

{% hint style="info" %}
Local volume mounts only work with local Kubernetes clusters (Docker Desktop, kind, minikube, Orbstack, etc.). They cannot be used with remote clusters because `hostPath` volumes reference the node's filesystem.
{% endhint %}

### Configuration

Add `localVolumes` to a `kubernetes` or `helm` Deploy spec:

```yaml
kind: Deploy
name: frontend
type: kubernetes
spec:
  manifestFiles: [./manifests/**/*]

  defaultTarget:
    kind: Deployment
    name: frontend
    containerName: frontend # Optional. Defaults to the first container.

  localVolumes:
    volumes:
      - name: frontend-src
        sourcePath: . # Relative to this action's source directory
        containerPath: /app # Absolute path inside the container
```

When `localVolumes.volumes` is defined, volume mounts are enabled automatically. You can explicitly disable them by setting `localVolumes.enabled: false`.

#### Multiple volumes and per-volume targets

You can mount several directories and target different workloads or containers. Volumes without a `target` use the action's `spec.defaultTarget`:

```yaml
spec:
  defaultTarget:
    kind: Deployment
    name: backend
    containerName: app

  localVolumes:
    volumes:
      - name: backend-code
        sourcePath: backend
        containerPath: /var/code/backend

      - name: config-files
        sourcePath: config
        containerPath: /etc/app/config

      # This volume targets a different container in the same Deployment
      - name: sidecar-data
        target:
          kind: Deployment
          name: backend
          containerName: sidecar
        sourcePath: sidecar-data
        containerPath: /var/data
```

### Cluster-specific setup

Different local Kubernetes distributions handle host filesystem access differently. Garden automatically converts paths for each cluster type, but some require additional setup.

#### Docker Desktop (macOS and Windows)

No special setup needed. Docker Desktop exposes the host filesystem automatically.

#### Orbstack (macOS)

No special setup needed. Orbstack exposes the host filesystem at the same paths as the host.

#### kind

kind runs Kubernetes inside Docker containers, so host directories must be explicitly mounted into the kind node. Add `extraMounts` to your kind cluster configuration:

```yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraMounts:
      - hostPath: /path/to/your/project
        containerPath: /path/to/your/project
```

{% hint style="warning" %}
If the kind cluster was created without `extraMounts`, you need to recreate it. Garden will verify the mount at deploy time and show an error with instructions if the mount is missing.
{% endhint %}

#### minikube

minikube requires the `minikube mount` command to expose host directories. Garden will attempt to start this automatically at deploy time if the mount is not already active.

You can also start it manually:

```sh
minikube mount "/path/to/your/project:/path/to/your/project"
```

#### Docker Desktop on Linux

Docker Desktop on Linux mounts the host filesystem at `/host_mnt`. Garden handles this path conversion automatically — no manual setup is needed.

#### Path conversion summary

| Cluster type   | macOS                      | Linux                      | Windows                    |
| -------------- | -------------------------- | -------------------------- | -------------------------- |
| Docker Desktop | as-is                      | `/host_mnt` prefix         | Drive letter conversion    |
| Orbstack       | as-is                      | N/A                        | N/A                        |
| kind           | as-is (via extraMounts)    | as-is (via extraMounts)    | as-is (via extraMounts)    |
| minikube       | as-is (via minikube mount) | as-is (via minikube mount) | as-is (via minikube mount) |

### Interaction with code synchronization

Local volume mounts and [code synchronization](/features/code-synchronization) (sync mode) serve a similar purpose but use different mechanisms. If both are configured on the same action, **local volume mounts take precedence** and sync mode is skipped with a warning.

If you want to use sync mode instead, set `localVolumes.enabled: false` or remove the `localVolumes` block.

### Excluding subdirectories from the mount

When you mount a host directory into a container path, it completely replaces whatever was at that path in the container image. This means dependencies installed during `docker build` (e.g. `node_modules`, Python virtualenvs) will be hidden by the mount.

The `excludes` field solves this by overlaying `emptyDir` volumes on top of the host mount at the specified subdirectories. The container sees an initially empty directory at each excluded path and can repopulate it at startup (e.g. via `npm install` in an entrypoint script).

```yaml
spec:
  defaultTarget:
    kind: Deployment
    name: frontend

  localVolumes:
    volumes:
      - name: frontend-src
        sourcePath: .
        containerPath: /app
        excludes:
          - node_modules
          - .cache
```

This generates three volumes:

1. A `hostPath` volume mounting the host directory at `/app`
2. An `emptyDir` volume at `/app/node_modules`
3. An `emptyDir` volume at `/app/.cache`

The container's entrypoint can then install dependencies into the empty `node_modules` directory without being affected by the host's potentially incompatible or missing `node_modules`.

{% hint style="info" %}
Each exclude entry is a path relative to `containerPath`. Nested paths like `vendor/bundle` are supported.
{% endhint %}

#### When to use excludes vs. installing locally

| Approach                                     | Pros                                               | Cons                                                     |
| -------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------- |
| `excludes` + entrypoint install              | Works regardless of host OS, no local setup needed | Slower container startup (installs on every restart)     |
| Install locally (e.g. `npm install` on host) | Instant startup, shared dependencies               | Must match container's OS/arch, requires local toolchain |

You can also combine both: use `excludes` to mask the directory, then use an init container or entrypoint to copy dependencies from a known-good location in the image.

### Important notes

#### Volume name requirements

Volume names must be valid Kubernetes DNS labels: lowercase alphanumeric characters or dashes, starting and ending with an alphanumeric character (e.g. `my-volume-1`).

#### Source path requirements

The `sourcePath` must be a relative POSIX path within the action's source directory. Absolute paths and paths that escape the source directory (e.g. `../other-dir`) are not allowed.

### Example project

A complete example project is available in the Garden repository under [`examples/local-volume-mounts`](https://github.com/garden-io/garden/tree/0.14.20/examples/local-volume-mounts). It demonstrates a multi-service setup with a frontend using local volume mounts and a backend without.


# Automatic Environment Cleanup

### Overview

The Automatic Environment Cleanup (AEC) feature allows you to automatically clean up or pause environments in your Kubernetes cluster after a period of inactivity or on a scheduled basis. This helps reduce costs and resource usage by ensuring that unused environments don't consume cluster resources indefinitely.

{% hint style="info" %}
This feature requires [Garden version 0.14.10](https://github.com/garden-io/garden/releases/tag/0.14.10) (or newer) and is currently in beta. It's currently only available for the Kubernetes provider.
{% endhint %}

### How it Works

The AEC feature consists of two main components:

1. **AEC Agent**: A lightweight service that runs in your Kubernetes cluster and monitors environment activity
2. **Environment Configuration**: Project-level configuration that defines when and how environments should be cleaned up

The AEC agent runs continuously in your cluster, checking all Garden-managed namespaces for configured cleanup triggers. When a trigger condition is met, the agent performs the specified action:

* **Pause**: Scales down all workloads in the environment to zero replicas, preserving configuration and data
* **Cleanup**: Completely removes the environment namespace and all its resources

The agent tracks the last deployment time for each environment and compares it against your configured triggers. It also sends status updates to Garden Cloud, allowing you to monitor cleanup activities through the Garden Cloud dashboard.

### Quickstart

Follow these steps to quickly set up automatic environment cleanup:

#### 1. Prerequisites

* Working Garden configuration for a Kubernetes project
* Admin/owner access to your Garden Cloud organization
* Logged in to Garden Cloud via `garden login` from your project root

#### 2. Configure Environment Cleanup

Add AEC configuration to one of the environments in your `project.garden.yml`:

```yaml
kind: Project
name: my-project
environments:
  - name: <env-name>
    # Add the following:
    aec:
      triggers:
        - action: pause
          timeAfterLastUpdate:
            value: 1
            unit: days
        - action: cleanup
          timeAfterLastUpdate:
            value: 7
            unit: days
```

#### 3. Install the AEC Agent

Install the AEC agent in your Kubernetes cluster:

```bash
# For remote clusters
garden plugins kubernetes setup-aec --env <env-name>

# For local clusters (Docker Desktop, minikube, etc.)
garden plugins local-kubernetes setup-aec --env <local-env>
```

#### 4. Deploy Your Environment

Deploy to your environment:

```bash
garden deploy --env preview
```

That's it! Your environment will now be automatically paused after 1 day of inactivity and cleaned up after 7 days.

### Configuration

AEC is configured at the environment level in your project configuration. You define triggers that specify when cleanup should occur and what action to take.

For complete configuration reference, see the [`environments[].aec`](/reference/project-config#environmentsaec) section in the Project Configuration documentation.

#### Basic Configuration

Add the `aec` configuration to your environment in your `project.garden.yml` or `garden.yml` file:

```yaml
kind: Project
name: my-project
environments:
  - name: preview
    aec:
      triggers:
        - action: pause
          timeAfterLastUpdate:
            value: 1
            unit: days
        - action: cleanup
          timeAfterLastUpdate:
            value: 7
            unit: days
```

This configuration will:

1. Pause the environment after 1 day of inactivity
2. Clean up the environment after 7 days of inactivity

#### Schedule-Based Cleanup

You can also configure cleanup to happen on a schedule, regardless of activity:

```yaml
environments:
  - name: staging
    aec:
      triggers:
        - action: cleanup
          schedule:
            every: friday
            hourOfDay: 18
            minuteOfHour: 0
```

This will clean up the staging environment every Friday at 6:00 PM.

#### Advanced Configuration

Here's a more comprehensive example showing multiple triggers and different scenarios:

```yaml
environments:
  - name: development
    aec:
      # Disable AEC for this environment (useful with templating)
      disabled: false
      triggers:
        # Pause after 2 hours of inactivity during weekdays
        - action: pause
          timeAfterLastUpdate:
            value: 2
            unit: hours
        # Clean up every weekday at 7 PM
        - action: cleanup
          schedule:
            every: weekday
            hourOfDay: 19
            minuteOfHour: 0
        # Also clean up after 3 days of inactivity as a fallback
        - action: cleanup
          timeAfterLastUpdate:
            value: 3
            unit: days

  - name: feature-branch
    aec:
      triggers:
        # Quick cleanup for feature branches
        - action: cleanup
          timeAfterLastUpdate:
            value: 6
            unit: hours
```

### Installing the AEC Agent

Before the AEC feature can work, you need to install the AEC agent in your Kubernetes cluster. The agent is a lightweight service that monitors your environments and performs cleanup actions.

#### Prerequisites

* Garden Cloud account with a paid subscription
* Kubernetes cluster with Garden deployed
* Admin access to your Garden Cloud organization
* Logged in to Garden Cloud via `garden login`

#### Installation

Use the `garden plugins kubernetes setup-aec` command to install the agent:

```bash
garden plugins kubernetes setup-aec --env <env>
```

This command will:

1. Create a service account in Garden Cloud for the agent
2. Deploy the AEC agent to your cluster's system namespace
3. Configure the agent with the necessary permissions and credentials

The agent will be deployed as a Kubernetes Deployment in the same namespace where Garden's system components are installed (typically `garden-system`).

To install in a local Kubernetes cluster (e.g. Docker Desktop, minkube, Orbstack etc.) you can use:

```bash
garden plugins local-kubernetes setup-aec --env <local env name>
```

#### Verification

After installation, you can verify that the agent is running:

```bash
kubectl get deployments -n garden-system
```

You should see a deployment named `garden-aec-agent` in the running state.

### Monitoring and Logs

#### Viewing AEC Agent Logs

To monitor the AEC agent's activity and troubleshoot issues, you can view its logs using:

```bash
garden plugins kubernetes aec-logs --env <env>
```

To stream logs continuously (useful for monitoring):

```bash
garden plugins kubernetes aec-logs --env <env> -- --follow
```

If you're using a local Kubernetes cluster, use `garden plugins local-kubernetes` instead of `garden plugins kubernetes` in the above commands.

The logs will show:

* Environment scanning activity
* Trigger evaluations
* Cleanup actions performed
* Any errors or warnings

#### Garden Cloud Dashboard

The AEC agent sends status updates to Garden Cloud, allowing you to monitor cleanup activities through the Garden Cloud dashboard. You can see:

* Which environments are configured for AEC
* Recent cleanup actions
* Agent status and health

### Best Practices

#### 1. Start with Pause Actions

Begin with pause actions before implementing full cleanup to ensure your configuration works as expected:

```yaml
triggers:
  - action: pause
    timeAfterLastUpdate:
      value: 1
      unit: days
```

#### 2. Use Multiple Triggers

Combine inactivity-based and schedule-based triggers for comprehensive cleanup:

```yaml
triggers:
  # Pause after inactivity
  - action: pause
    timeAfterLastUpdate:
      value: 1
      unit: days
  # Clean up on weekends
  - action: cleanup
    schedule:
      every: sunday
      hourOfDay: 2
      minuteOfHour: 0
```

#### 3. Environment-Specific Configuration

Configure different cleanup policies for different environment types:

```yaml
environments:
  - name: production
    # No AEC for production
    aec:
      disabled: true

  - name: staging
    aec:
      triggers:
        - action: cleanup
          timeAfterLastUpdate:
            value: 3
            unit: days

  - name: preview
    aec:
      triggers:
        # Aggressive cleanup for preview environments
        - action: cleanup
          timeAfterLastUpdate:
            value: 6
            unit: hours
```

#### 4. Use Templating for Dynamic Configuration

Leverage Garden's templating to make AEC configuration dynamic:

```yaml
environments:
  - name: dev
    aec:
      disabled: ${var.aec-disabled || false}
      triggers:
        - action: cleanup
          timeAfterLastUpdate:
            value: ${var.cleanup-hours || 24}
            unit: hours
```

### Troubleshooting

#### Agent Not Starting

If the AEC agent fails to start:

1. Check the agent logs: `garden plugins kubernetes aec-logs`
2. Verify Garden Cloud connectivity
3. Ensure your Garden Cloud subscription includes AEC
4. Check Kubernetes permissions and resources

#### Environments Not Being Cleaned Up

If environments aren't being cleaned up as expected:

1. Verify the environment has the correct Garden annotations
2. Check that triggers are properly configured
3. Review agent logs for trigger evaluation messages
4. Ensure the environment has been deployed at least once (to establish a "last update" time)

#### Unexpected Cleanup

If environments are being cleaned up unexpectedly:

1. Review your trigger configuration
2. Check the agent logs to see which trigger was matched
3. Verify the last deployment time of the environment
4. Consider using more conservative time periods initially

### Limitations

* Currently only available for the Kubernetes provider
* Requires a Garden Cloud account
* The feature is in beta and may have limitations or changes
* Schedule-based triggers use the cluster's timezone
* Minimum cleanup interval is 1 minute (agent check frequency)

### Security Considerations

The AEC agent requires permissions to:

* List and read namespaces in the cluster
* Scale deployments and statefulsets to zero (for pause action)
* Delete namespaces (for cleanup action)
* Read and write namespace annotations

These permissions are automatically configured during installation, but ensure your cluster security policies allow these operations.


# Terraform

Garden includes a Terraform provider that you can use to automatically validate and provision infrastructure as part of your project. This guide walks through how to configure and use the provider.

It's strongly recommended that you [learn about Terraform](https://developer.hashicorp.com/terraform/docs) (if you haven't already) before using it with Garden.

### How it works

Under the hood, Garden simply wraps Terraform, so there's no magic involved. Garden just automates its execution and makes stack outputs available to your Garden providers and actions.

Terraform resources can be provisioned through the `terraform` provider when initializing Garden, or via `terraform` actions that are utilized like other actions in your stack.

The former, having a single Terraform stack for your whole project, is most helpful if other provider configurations need to reference the outputs from your Terraform stack, or if most/all of your services depend on the infrastructure provisioned in your Terraform stack. A good example of this is the [terraform-gke example](https://github.com/garden-io/garden/tree/0.14.20/examples/terraform-gke) project, which provisions a GKE cluster that the `kubernetes` provider then runs on, along with the services in the project. The drawback is that Garden doesn't currently watch for changes in those Terraform files, and you need to restart to apply new changes, or apply them manually.

Using `terraform` *Deploy actions*, can be better if your other providers don't need to reference the stack outputs but other Deploy, Run and Test actions do. In this style, you can basically create small Terraform stacks that are part of your Stack Graph much like other services. A good example would be deploying a database instance, that other services in your project can then connect to.

You can also use a combination of the two if you'd like. Below we'll walk through how each of these work.

### Planning and applying

Garden will not automatically apply the Terraform stack, unless you explicitly set the `autoApply` flag on the config for the stack. Instead, Garden will warn you if the stack is out of date.

{% hint style="warning" %}
We only recommend using `autoApply` for private development environments, since otherwise you may accidentally apply hazardous changes, or conflict with other users of an environment.
{% endhint %}

To manually plan and apply stacks, we provide the following commands:

```console
garden --env=<env-name> plugins terraform apply-root                     # Runs `terraform apply` for the provider root stack.
garden --env=<env-name> plugins terraform apply-action -- <action-name>  # Runs `terraform apply` for the specified terraform Deploy action.
garden --env=<env-name> plugins terraform plan-root                      # Runs `terraform plan` for the provider root stack.
garden --env=<env-name> plugins terraform plan-action -- <action-name>   # Runs `terraform plan` for the specified terraform Deploy action.
```

Each command automatically applies any variables configured on the provider or action in question. Any additional arguments you specify for the command are passed directly to the `terraform` CLI command, but you need to place them after a `--` so that they aren't parsed as Garden options. For example, to apply the root stack with `-auto-approve`:

```console
garden --env=<env-name> plugins terraform apply-root -- -auto-approve
```

### Setting the backend dynamically

[Terraform does not interpolate named values in backend manifests](https://developer.hashicorp.com/terraform/language/backend) but with Garden you can achieve this via the `backendConfig` field on either the `terraform` provider or action configuration. This enables you to dynamically set the backend when applying your Terraform stack in different environments.

For example, running `garden deploy --env dev` and `garden deploy --env ci` will pick the appropriate backend for the environment.

If you'd like to apply the stack when starting Garden (e.g. because you're provisioning a Kubernetes cluster and need to pass the outputs to other Garden providers), check out [the Terraform provider docs for configuring dynamic backends](/using-garden-with/terraform/configure-provider#setting-the-backend-dynamically).

If instead you configure your Terraform stack via actions (e.g. because you have multiple AWS labmdas that should each have their own stack), check out [the Terraform action docs for configuring dynamic backends](/using-garden-with/terraform/actions#setting-the-backend-dynamically).

### Next steps

Check out how to configure the Terraform provider and/or actions in the following pages. You'll find some [Terraform examples here](https://github.com/garden-io/garden/tree/0.14.20/examples).


# Using Terraform

First off, you need to enable the provider in your project configuration. This is as simple as placing it in your list of providers:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
providers:
  - name: terraform
  - name: kubernetes
  ...
```

If you'd like to apply the stack when starting Garden, and then reference the stack outputs in other providers (or actions), you need to add a couple of more flags. Here's the project config from the aforementioned [terraform-gke example](https://github.com/garden-io/garden/tree/0.14.20/examples/terraform-gke):

```yaml
apiVersion: garden.io/v2
kind: Project
name: terraform-gke
providers:
  - name: terraform
    # This must be set if we want to resolve a stack as part of the provider initialization.
    initRoot: "."
    # You can either replace these with your own values, or delete these and provide your own in a
    # terraform.tfvars file in the project root.
    variables:
      gcp_project_id: garden-gke-tf-1
      gcp_region: europe-west1
  - name: kubernetes
    kubeconfig: ${providers.terraform.outputs.kubeconfig_path}
    context: gke
    defaultHostname: terraform-gke-${local.username}.dev-2.sys.garden
    buildMode: kaniko
```

The `initRoot` parameter tells Garden that there is a Terraform working directory at the specified path. If you don't specify this, Garden doesn't attempt to apply a stack when initializing the provider.

Notice also that we're providing an output value from the stack to the `kubernetes` provider. This can be very powerful, and allows you to fully codify your full project setup, not just the services running in your environment. Any Garden action can also reference the provider outputs in the exact same way, so you can easily provide your services with any information they need to operate.

### Setting the backend dynamically

[Terraform does not interpolate named values in backend manifests](https://developer.hashicorp.com/terraform/language/backend) but with Garden you can achieve this via the `backendConfig` field on the Terraform provider. This enables you to dynamically set the backend when applying your Terraform stack in different environments.

#### Example - Provision a K8s cluster per environment

In the example below we can imagine a Terraform stack that provisions a Kubernetes cluster when Garden starts and passes the output to other providers (similar to the example above) and picks a backend dynamically depending on the environment.

We achieve this via the `backendConfig` field on the `terraform` provider spec which can make use of Garden's powerful templating system.

This means you can run `garden deploy` (for the dev env) and it will use the corresponding backend. From the same host you could then run `garden deploy --env` without needing to update your config and manually re-intialize Terraform, and it will again pick the correct backend.

```yaml
# In project.garden.yml file
apiVersion: "garden.io/v2"
kind: Project
name: terraform-lambda-example
defaultEnvironment: dev

environments:
  - dev
  - ci

providers:
  - name: terraform
    initRoot: "."
    # Pick the right S3 bucket and key for the environment
    backendConfig:
      bucket: my-${environment.name}-bucket
      key: tf-state/${environment.name}/terraform.tfstate
  - name: kubernetes
    kubeconfig: ${providers.terraform.outputs.kubeconfig_path}
# ...
```

A corresponding Terraform `main.tf` file would look like this:

```hcl
terraform {
  required_version = ">= 0.12"
  backend "s3" {
    bucket = ""
    key    = ""
    region = "<my-aws-region>"
  }
}
# ...
```


# Applying Terrform Stacks

{% hint style="info" %}
To apply Terraform stacks before actions (e.g. to provision a K8s cluster), refer to the [Terraform provider docs](/using-garden-with/terraform/configure-provider).
{% endhint %}

You can define `terraform` actions as part of your project, much like any other actions. A `terraform` action maps to a single `Deploy` that you can define as a runtime dependency for any of your other `Deploy`, `Run` and `Test` actions. You can also reference the stack outputs of a `terraform` action using [runtime output template strings](/features/variables-and-templating#runtime-outputs). For example:

```yaml
kind: Deploy
type: terraform
name: tf
spec:
  autoApply: true

---
kind: Deploy
type: container
name: my-container
# Important! You must declare the terraform service as a dependency, for the runtime template string to work.
dependencies: [deploy.tf]
spec:
  env:
    DATABASE_URI: ${runtime.services.tf.outputs.my-database-uri}
```

Here we imagine a Terraform stack that has a `my-database-uri` output, that we then supply to `my-service` via the `DATABASE_URI` environment variable.

Much like other Deploy actions, you can also reference Terraform definitions in other repositories using the `repositoryUrl` key. See the \[Remote Sources]\(../features/custom-commands.md

### Setting the backend dynamically

[Terraform does not interpolate named values in backend manifests](https://developer.hashicorp.com/terraform/language/backend) but with Garden you can achieve this via the `backendConfig` field on the `terraform` Deploy action. This enables you to dynamically set the backend when applying your Terraform stack in different environments.

#### Example - Isolated namespaces for Labmda functions

In the example below we can imagine a project with multiple AWS Lambda functions and a Terraform stack per function. Splitting the functions into individual stacks is useful for leveraging Garden's graph and cache capabilities. For example, you can granularly deploy or test individual lambdas instead of having everything bundled together in big stack.

Here we namespace the Lambdas such that each developer and CI run gets its own isolated namespace which can be cleaned up after the run.

We achieve this via the `backendConfig` field on the `terraform` Deploy action spec which can make use of Garden's powerful templating system.

```yaml
# In project.garden.yml file
apiVersion: "garden.io/v2"
kind: Project
name: terraform-lambda-example
defaultEnvironment: dev

environments:
  - name: dev
    variables:
      tfNamespace: ${kebabCase(local.username)} # <--- Each user has their own set of lambdas
  - name: ci
    variables:
      tfNamespace: ${slice(git.commitHash, 0, 7) || '<detached>'} # <--- Each CI run has its own set of lambdas

---
kind: Deploy
name: function-a
type: terraform
spec:
  root: ./tf/function-a
  variables:
    function_name_prefix: ${var.tfNamespace} # <--- This would get passed to Terraform to ensure the function names are unique
  backendConfig:
    bucket: my-${environment.name}-bucket
    key: tf-state/${var.tfNamespace}/terraform.tfstate
---
kind: Deploy
name: function-b
type: terraform
spec:
  root: ./tf/function-b
  variables:
    function_name_prefix: ${var.tfNamespace}
  backendConfig:
    bucket: my-${environment.name}-bucket
    key: tf-state/${var.tfNamespace}/terraform.tfstate
```

The corresponding Terraform `main.tf` files would look something like this:

```hcl
# For example in ./tf/function-a/main.tf
terraform {
  required_version = ">= 0.12"
  backend "s3" {
    bucket = ""
    key    = ""
    region = "<my-aws-region>"
  }
}
# ...
```

Note that this same pattern of course applies to other cloud providers and/or resources as well.

You can use the `garden cleanup` function to cleanup namespaces. It's also useful to have a lifecycle policy for cleaning up S3 buckets in non-prod environments.


# Pulumi

{% hint style="warning" %}
The Pulumi plugin is already being used in large projects, but is still considered experimental. Please let us know if you have any questions or if any issues come up!
{% endhint %}

Garden includes an experimental Pulumi plugin that wraps the Pulumi CLI. This way, you can incorporate Pulumi stacks into your Garden project with minimal extra configuration. The benefits of using this plugin include:

* Leveraging Garden's dependency semantics with your Pulumi stacks.
  * For example, Kubernetes actions can depend on infrastructure deployed with Pulumi (and access stack outputs via the `${actions.deploy.[pulumi-deploy-action-name].outputs})` key).
  * Deploy, preview, update, refresh or destroy Pulumi stacks in dependency order with a single command.
* Fast incremental deploys that use Garden's versioning system in combination with Pulumi stack tags to implement efficient service status checks.

We strongly recommend that you [learn about Pulumi](https://www.pulumi.com/docs/) (if you haven't already) before using it with Garden.

### How it works

Internally, Garden simply wraps the Pulumi CLI, calling the appropriate Pulumi CLI commands to deploy, delete or check the status of a service.

The Pulumi plugin can optionally make use of stack tags to implement fast service status checks, which can be a major boost to performance when deploying projects containing several Pulumi stacks.

Finally, the plugin defines several plugin-specific commands that let you run Pulumi commands in one or more Pulumi deploy actions *in dependency order* (which can be very useful for projects with several Pulumi stacks).

### Deploying your Pulumi stacks

Once you've got your Pulumi deploy actions configured, they will be deployed when you run `garden deploy` in your project; just like any other Garden deploy!

### Referencing stack outputs in other Garden actions

Pulumi stacks can define [stack outputs](https://www.pulumi.com/docs/intro/concepts/stack/#outputs).

These can then be read by other Pulumi stacks via [stack references](https://www.pulumi.com/docs/intro/concepts/stack/#stackreferences).

Garden's dependency graph functionality is a great fit for stack references. For example, if `pulumi-deploy-action-a`'s Pulumi program uses a stack references to an IP address that's an output of `pulumi-deploy-action-b`'s Pulumi program, you can add a dependency on `pulumi-deploy-action-b` by referencing that output:

```yaml
kind: Deploy
type: pulumi
name: pulumi-deploy-action-a
spec:
  cacheStatus: true
  # Here, you should list all stack references used by this action's pulumi program.
  stackReferences:
    - ${actions.deploy.pulumi-deploy-action-b.outputs.ip-address}
  # Make sure to add a dependency on each pulumi action you're using for stack references
  # above (otherwise an error will be thrown when you deploy).
  dependencies:
    - deploy.pulumi-deploy-action-b
```

This ensures that Garden deploys `pulumi-deploy-action-b` before `pulumi-deploy-action-a` when running e.g. `garden deploy`.

If you make sure to include all stack references to Pulumi deploy actions in your project in the `stackReferences` field, you can safely set `cacheStatus: true` for your deploy action, since Garden will factor the stack output values into its version calculations.

If `cacheStatus` is set to `false`, Garden runs `pulumi up` on every deploy. While this is safe and easy to reason about, it's much slower and more resource-intensive than using `cacheStatus = true`.

This is because running `pulumi up` is a much more expensive operation (in terms of CPU, RAM and time used) than the calls to `pulumi stack tag set/get` that Garden uses when `cacheStatus = true`.

With that in mind, we recommend using `cacheStatus = true` in your pulumi deploy actions whenever possible, once you've made sure you've included all relevant stack references in your pulumi deploy action configs. However, setting `cacheStatus = true` is only possible for Pulumi cloud managed state backends.

### Plugin commands

The pulumi plugin also comes with plugin-specific commands, which are designed to run pulumi commands in dependency order (and with access to Garden's full config/templating capabilities).

The currently available plugin commands are:

* `preview`
* `cancel`
* `refresh`
* `destroy`
* `reimport`\
  Each of the above wraps the pulumi command with the same name, except for `reimport` (which wraps `pulumi export | pulumi import`—a workflow that's occasionally needed).

By default, each command runs for every pulumi deploy action in the project. Each plugin command also accepts an optional list of pulumi deploy action names as CLI arguments.

When a list of deploy action names is provided, the pulumi command will only be run for those deploy actions (still in dependency order).

For example:

```
garden plugins pulumi preview -- my-pulumi-deploy-action my-other-pulumi-deploy-action
```

### Pulumi varfile schema

By default Garden uses a schema for the Pulumi varfiles that expects all content in a varfile to be values that are set under the `config` key in the pulumi config file. Garden will resolve any template strings in varfiles and then add them to the `config` section of the pulumi config file.

Example of old varfile schema:

```
kubernetes:context: orbstack
pulumi-k8s:namespace: ns-from-the-varfile
```

Since this does not allow for setting other top-level values like e.g. `secretsprovider` this schema has been updated and now requires config values to be referenced under the `config` key.

Example of new varfile schema:

```
secretsprovider: gcpkms://projects/xyz/locations/global/keyRings/pulumi/cryptoKeys/pulumi-secrets
encryptedkey: 123456
config:
  kubernetes:context: orbstack
  pulumi-k8s:namespace: ns-from-the-varfile
```

To use the new schema in a single pulumi deploy action set `action.spec.useNewPulumiVarfileSchema` to `true`. To use\
the new schema for all of your pulumi deploy actions set `useNewPulumiVarfileSchema` in your pulumi provider to `true`. The flag will be removed in the next major release and the new schema will be used.

### Next steps

Check out the [`pulumi` example](https://github.com/garden-io/garden/blob/latest-release/examples/pulumi/README.md) project.

Also take a look at the [pulumi provider reference](/reference/providers/pulumi) and the [pulumi's deploy action type reference](/reference/action-types/deploy/pulumi) for details on all the configuration parameters.

If you're having issues with pulumi itself, please refer to the [official docs](https://www.pulumi.com/docs/).


# Using Pulumi

First, you need to enable the `pulumi` provider in your project configuration. This is as simple as placing it in your list of providers:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
providers:
  - name: pulumi # <----
  ...
```

In case you want to use different backends for different Garden environments you can configure your provider and deploy actions follows. This example uses two different pulumi backends. In the `dev` environment it uses a self-managed state backend, in this case an S3 bucket which is specified with the `backendURL`. In the `prod` environment it uses pulumi managed state backend, which is the default so we don't need to specify a `backendURL`.

Note that when you use a self managed state backend, Garden's deploy action level `spec.cacheStatus` needs to be set to `false`, since caching is only available with the pulumi managed state backend. The same applies to `spec.orgName` which only makes sense in the context of the pulumi managed state backend. Please ensure that `spec.orgName` is set to `null` or empty string `""` for all the environments that are not using the pulumi managed state backend.

```yaml
---
apiVersion: garden.io/v2
kind: Project
name: pulumi
defaultEnvironment: dev
variables:
  cacheStatus: true
environments:
  - name: dev
    variables:
      backendURL: s3://<bucket-name>
      cacheStatus: false # cacheStatus has to be set to false for self-managed state backends
  - name: prod
    variables:
      orgName: garden
providers:
  - name: pulumi
    environments: [dev, prod]
    orgName: ${var.orgName || null} # ensure orgName is null or "" for self-managed state backends
    backendURL: ${var.backendURL || null} # defaults to Pulumi managed state backend if null or ""

---
kind: Deploy
type: pulumi
name: aws-s3
description: Creates an s3 bucket
spec:
  createStack: true
  cacheStatus: ${var.cacheStatus} # cacheStatus has to be set to false for self-managed state backends
  stack: ${environment.name}
  pulumiVariables:
    environment: ${environment.name}
```

There are several configuration options you can set on the provider—see the [reference docs for the pulumi provider](/reference/providers/pulumi) for details.


# Applying Pulumi Stacks

## Deploy Action

You need to write Garden Deploy action configs next to the pulumi stacks you'd like to include in your project. These should be located in the same directory as the stack config, or in an enclosing directory.

For example:

```yaml
kind: Deploy
type: pulumi
name: my-pulumi-deploy-action
spec:
  # If the pulumi stack doesn't exist already when deploying, create it
  createStack: true
  # Cache deploys based on the Garden service version (see the section below)
  # Setting `cacheStatus = true` works only with Pulumi service managed state backends.
  cacheStatus: true
  # These variables will be merged into the stack config before deploying or previewing
  pulumiVariables:
    my-variable: pineapple
  # Variables defined in varfiles will also be merged into the stack config in declaration
  # order (and take precedence over variables defined in this Deploy action's pulumiVariables).
  pulumiVarfiles: [my-default-varfile.yaml, dev.yaml]
```

In case you want to use different backends for different Garden environments and you want to use deploy action specific pulumi managed state backend organizations, you can configure your deploy actions as follows. This example uses two different pulumi backends. For the `prod` environment it uses the pulumi managed state backend and for the `dev` environment it uses a self managed S3 backend.

Note that when you use a self managed state backend `spec.cacheStatus` needs to be set to `false`, since caching is only available with the pulumi managed state backend. The same applies to `spec.orgName` which only makes sense in the context of the pulumi managed state backend. Please ensure that `spec.orgName` is set to `null` or empty string `""` for all the environments that are not using the pulumi managed state backend.

```yaml
apiVersion: garden.io/v2
kind: Project
name: pulumi
defaultEnvironment: dev
environments:
  - name: dev
    variables:
      backendURL: s3://<bucket-name>
  - name: prod
providers:
  - name: pulumi
    environments: [dev, prod]
    backendURL: ${var.backendURL || null} # backendURL defaults to the pulumi managed state backend if null or empty string ""
---
kind: Deploy
type: pulumi
name: s3stack
spec:
  stack: s3
  orgName: '${environment.name == "prod" ? "s3stack-prod" : ""}' # orgName has to be null or an empty string "" for self-managed state backends
  createStack: true
  cacheStatus: '${environment.name == "prod" ? true : false}' # cacheStatus has to be set to false for self-managed state backends
  description: Creates an s3 bucket
  pulumiVariables:
    environment: ${environment.name}
```

See the [reference docs for the pulumi deploy action type](/reference/action-types/deploy/pulumi) for more info on each available config field (and how/when to use them).


# Local Scripts

You can run scripts locally on the host (e.g. your laptop or your CI runner) with the `exec` action.

A common use case is running auth scripts as well as executing various scaffolding scripts that need to run "locally".

It can also be used to start applications locally (e.g. by executing commands like `npm run dev`).

This can be very useful for hybrid environments where you have, say, your backend running in a remote production-like environment but your frontend running locally.

### Provider Configuration

Usually you don't need to configure the `exec` provider because it's built-in and you can use `exec` actions directly.

However, it can be used to run init scripts ahead of other Garden execution. This is useful if you need to authenticate against a remote environment before Garden initializes other plugins.

Here's an example where we run a script to authenticate against a Kubernetes cluster before initializing the Kubernetes plugin:

```yaml
# In your project level Garden config file
apiVersion: garden.io/v2
kind: Project
name: my-project

providers:
  - name: exec
    initScript: "sh -c ./scripts/auth.sh"
  - name: kubernetes
    dependencies: [exec] # <--- This ensures the init script runs before the K8s plugin is initialized.
    # ...
```

The log output of the `initScript` can be accessed via `"${providers.exec.outputs.initScript.log}"` template string.

### Actions

#### Build

A Build action which executes a build command "locally" on the host.

This is commonly used together with exec Deploy actions when a local build step needs to be executed first.

{% hint style="info" %}
Note that by default, Garden will "stage" the build to the `./garden` directory and execute the build there. This is to ensure that the command doesn't mess with your local project files. You can disable that by setting `buildAtSource: true`.
{% endhint %}

For example:

```yaml
# In ./lib
kind: Build
name: lib-local
type: exec
buildAtSource: true # <--- Here we want execute the build in the ./lib dir directly
spec:
  command: [npm, run, build]
---
# In ./web
kind: Deploy
name: web-local
type: exec
dependencies: [build.lib-local] # <--- Build lib before starting local dev server
spec:
  persistent: true
  deployCommand: [npm, run, dev]
```

Another common use case is to prepare a set of files, say, manifests ahead of a deployment. In this case we choose to execute the script in the `./garden` directory so that it doesn't affect our version controlled source code.

That's why we also need to set the `build` field on the Deploy action.

```yaml
# In ./manifests dir
kind: Build
name: prepare-manifests
type: exec
spec:
  command: [./prepare-manifests.sh]
---
kind: Deploy
name: api
type: kubernetes
build: prepare-manifests # <--- This tells Garden to use the build directory for the 'prepare-manifests' action as the source for this action.
dependencies: [build.prepare-manifests]
```

#### Deploy

A Deploy action which executes a deploy command "locally" on the host.

This is commonly used for hybrid environments where you e.g. deploy your backend services to a remote Kubernetes cluster but run your web service locally.

If you're starting a long running local process, you need to set `persistent: true`. Note that you can also specify a `statusCommand` that tells Garden when the command should be considered ready and a `cleanupCommand` that's executed when running the Garden `cleanup` command.

For example:

```yaml
# In ./api
kind: Deploy
name: api
type: kubernetes
# ...
# In ./web
kind: Deploy
name: web
type: exec
spec:
  persistent: true
  deployCommand: [npm, run, dev]
  statusCommand: [./is-ready.sh] # <--- Garden checks the status at an interval until the command returns 0 or times out
  cleanupCommand: [npm, run, clean]
```

You'll find a complete example of this in our [local-service example project](https://github.com/garden-io/garden/blob/latest-release/examples/local-service/README.md).

#### Run and Test

Similar to the Build action, the Run and Test actions can also be used to run one-off local commands.

Following are some example `exec` Run actions for executing various scripts:

```yaml
kind: Run
name: auth
type: exec
spec:
  command: ["sh", "-c", "./scripts/auth.sh"]

---
kind: Run
name: prepare-data
type: exec
spec:
  command: ["sh", "-c", "./scripts/prepare-data-locally.sh"]
```

Other actions can depend on these Runs:

```yaml
kind: Run
name: db-init
type: exec
dependencies: [run.auth, run.prepare-data]
spec:
  command: [npm, run, db-init]
```

It's also possible to reference the output from `exec` actions:

```yaml
kind: Deploy
name: postgres
type: container
spec:
  image: postgres:15.3-alpine
  ports:
    - name: db
      containerPort: 5432
  env:
    POSTGRES_DATABASE: postgres
    POSTGRES_USERNAME: postgres
    POSTGRES_PASSWORD: ${actions.run.auth.outputs.log}
```

### Next Steps

For some advanced `exec` use cases, check out [this recording](https://www.youtube.com/watch?v=npE0FWJwcno) of our community office hours on the topic.


# Remote Container Builder

The Remote Container Builder enables you to build container images using **blazing-fast, remote build compute instances** managed by Garden. Each built layer of your Dockerfile is stored on low-latency, high-throughput NVMe storage so that your entire team can benefit from shared build caches. This can result in [significantly faster builds](/overview/case-studies/oem-cloud-builder).

Our free-tier includes a certain amount of build minutes and GBs of layer caching per month and you get more by switching to our team or enterprise tiers. You can learn more about the [different tiers here](https://app.garden.io/plans).

You can also use the [Builds UI](https://app.garden.io) to view build logs and analyze bottlenecks in your builds.

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/build-ui.gif" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/build-ui.gif" alt="Build UI"></picture><figcaption><p>Build UI</p></figcaption></figure>

### Using the Remote Container Builder

To use the Remote Container Builder you need to first [connect your project to the Garden Cloud backend](/guides/connecting-project).

The container builder is enabled by default so no further configuration is required.

You can learn more about configuring the container builder and e.g. only enabling it in certain environments in [this guide](/using-garden-with/containers/using-remote-container-builder).


# Team Caching

One of the most important features of Garden is its smart caching abilities. Garden calculates the version of each action, based on the source files and configuration involved, as well as any upstream dependencies. When using Garden, you'll see various instances of `v-<some hash>` strings scattered around logs, e.g. when building, deploying, running tests, etc.

These versions are used by Garden to work out which actions need to be performed whenever you want to build, deploy or test your project.

The version is stored in the [Garden Cloud backend](https://app.garden.io) and can be shared with your team and across CI runs. This means that if you open a pull request that triggers several Test actions to be run, then push a new commit that only changes files that belong to one of the tests, only that test will re-run.

Our free-tier has limits on cache retention and number of cache hits that you can increase by switching to our team or enterprise tiers. You can learn more about the [different plans here](https://app.garden.io/plans).

![Run a test that passes then run it again. Note that the second time it's cached.](https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/team-cache-gif.gif)

### Using Team Caching

Team Caching is enabled automatically as long you've [connected your project to the Garden Cloud backend](/guides/connecting-project).


# Variables and Templating

Garden has a powerful templating engine that allows you to set variables and enable or disable parts of the graph depending on your environment.

### Template string overview

String configuration values in Garden config files can be templated to inject variables, information about the user's environment, references to other actions and more.

The basic syntax for templated strings is `${some.key}`. The key is looked up from the *template context* available when resolving the string. The available context depends on what is being resolved, i.e. a *project*, *action*, *provider* etc.

For example, for one action you might want to reference something from another action and expose it as an environment variable:

```yaml
kind: some-action
spec:
  env:
    OTHER_ACTION_VERSION: ${actions.build.some-build.version}
```

You can also inject a template variable into a string. For instance, you might need to include an actions's\
version as part of a URI:

```yaml
OTHER_ACTION_ENDPOINT: http://other-module/api/${actions.deploy.some-deploy.version}
```

Note that while this syntax looks similar to template strings in Javascript, we don't allow arbitrary JS expressions. See the next section for the available expression syntax.

#### Literals

In addition to referencing variables from template contexts, you can include a variety of *literals* in template strings:

* *Strings*, including concatenated ones, enclosed with either double or single quotes: `${"foo"}`, `${'bar'}`, `${'bar' + 'foo}`.
* *Numbers*: `${123}`
* *Booleans*: `${true}`, `${false}`
* *Null*: `${null}`
* *Arrays*: `${[1, 2, 3]}`, `${["foo", "bar"]}`, `${[var.someKey, var.someOtherKey]}`, `${concat(["foo", "bar"], ["baz"])}`, `${join(["foo", "bar"], ",")}`

These can be used with [operators](#operators), as [helper function arguments](#helper-functions) and more.

#### Operators

You can use a variety of operators in template string expressions:

* Arithmetic: `*`, `/`, `%`, `+`, `-`
* Numeric comparison: `>=`, `<=`, `>`, `<`
* Equality: `==`, `!=`
* Logical: `&&`, `||`, ternary (`<test> ? <value if true> : <value if false>`)
* Unary: `!` (negation), `typeof` (returns the type of the following value as a string, e.g. `"boolean"` or `"number"`)
* Relational: `contains` (to see if an array contains a value, an object contains a key, or a string contains a substring)
* Arrays: `+`
* Strings: `+`

The arithmetic and numeric comparison operators can only be used for numeric literals and keys that resolve to numbers, except the `+` operator which can be used to concatenate two strings or array references. The equality and logical operators work with any term (but be warned that arrays and complex objects aren't currently compared in-depth).

Clauses are evaluated in standard precedence order, but you can also use parentheses to control evaluation order (e.g. `${(1 + 2) * (3 + 4)}` evaluates to 21).

These operators can be very handy, and allow you to tailor your configuration depending on different environments and other contextual variables.

Below are some examples of usage:

The `||` operator allows you to set default values:

```yaml
kind: Deploy
variables:
  log-level: ${local.env.LOG_LEVEL || "info"}
  namespace: ${local.env.CI_BRANCH || local.username || "default"}
```

The `==` and `!=` operators allow you to set boolean flags based on other variables:

```yaml
kind: Deploy
disabled: ${environment.name == 'prod'}
```

```yaml
kind: Build
allowPublish: ${environment.name != 'prod'}
```

Ternary expressions, combined with comparison operators, can be useful when provisioning resources:

```yaml
kind: Deploy
type: container
spec:
  replicas: "${environment.name == 'prod' ? 3 : 1}"
```

The `contains` operator can be used in several ways:

* `${var.some-array contains "some-value"}` checks if the `var.some-array` array includes the string `"some-value"`.
* `${var.some-string contains "some"}` checks if the `var.some-string` string includes the substring `"some"`.
* `${var.some-object contains "some-key"}` checks if the `var.some-object` object includes the key `"some-key"`.

The arithmetic operators can be handy when provisioning resources:

```yaml
kind: Deploy
type: container
spec:
  replicas: ${var.default-replicas * 2}
  cpu:
    max: ${var.default-cpu-max + 2000}
```

And the `+` operator can also be used to concatenate two arrays or strings:

```yaml
apiVersion: garden.io/v2
kind: Project
variables:
  some-values: ["a", "b"]
  other-values: ["c", "d"]
  str1: "foo"
  str2: "bar"
---
kind: Deploy
type: helm
values:
  some-array: ${var.some-values + var.other-values}
  str12: ${var.str1 + var.str2}
```

#### Helper functions

You can use a variety of helper functions in template strings, for things like string processing, parsing, conversions etc. You find a [full list in the reference docs](/reference/template-strings/functions), but here are a couple of examples:

* `${base64Encode('my value')}` encodes the `'my value'` string as base64.
* `${base64Decode('bXkgdmFsdWU=')}` decodes the given base64 string.
* `${replace(var.someVariable, "_", "-")}` returns the `someVariable` variable with all underscores replaced with dashes.

Check out [the reference](/reference/template-strings/functions) to explore all the available functions.

#### If/else conditional objects

You can conditionally set values by specifying an object with `$if`, `$then` and (optionally) `$else` keys. This can in many cases be clearer and easier to work with, compared to specifying values within conditional template strings.

Here's an example:

```yaml
kind: Deploy
spec:
  command:
    $if: ${this.mode == "sync"}
    $then: [npm, run, watch]
    $else: [npm, start]
```

This sets `spec.command` to `[npm, run, watch]` when the action is in sync mode, otherwise to `[npm, start]`.

You can also skip the `$else` key to default the conditional to *no value* (i.e. undefined).

#### Multi-line if/else blocks in strings

You can use if/else blocks in strings. These are particularly handy when templating multi-line strings and generated files in [action templates](/features/config-templates).

The syntax is `${if <expression>}<content>[${else}]<alternative content>${endif}`, where `<expression>` is any expression you'd put in a normal template string.

Here's a basic example:

```yaml
variables:
  some-script: |
    #!/bin/sh
    echo "Hello, I'm a bash script!"

    ${if environment.name == "dev"}
    echo "-> debug mode"
    DEBUG=true
    ${else}
    DEBUG=false
    ${endif}
```

You can also nest if-blocks, should you need to.

#### Nested lookups and maps

In addition to dot-notation for key lookups, we also support bracketed lookups, e.g. `${some["key"]}` and `${some-array[0]}`.

This style offer nested template resolution, which is quite powerful, because you can use the output of one expression to choose a key in a parent expression.

For example, you can declare a mapping variable for your project, and look up values by another variable such as the current environment name. To illustrate, here's an excerpt from a project config with a mapping variable:

```yaml
apiVersion: garden.io/v2
kind: Project
variables:
  - replicas:
      dev: 1
      prod: 3
```

And here that variable is used in a Deploy:

```yaml
kind: Deploy
type: container
spec:
  replicas: ${var.replicas["${environment.name}"]}
```

When the nested expression is a simple key lookup like above, you can also just use the nested key directly, e.g. `${var.replicas[environment.name]}`.

You can even use one variable to index another variable, e.g. `${var.a[var.b]}`.

#### Concatenating lists

Any list/array value supports a special kind of value, which is an object with a single `$concat` key. This allows you to easily concatenate multiple arrays.

Here's an example where we concatenate the same templated value into two arrays of test arguments:

```yaml
kind: Module
...
variables:
  commonArgs:
    - npm
    - test
    - -g
tests:
  - name: test-a
    # resolves to [npm, test, -g, suite-a]
    args:
      - $concat: ${var.commonArgs}
      - suite-a
  - name: test-b
    # resolves to [npm, test, -g, suite-b]
    args:
      - $concat: ${var.commonArgs}
      - suite-b
```

#### For loops

You can map through a list of values by using the special `$forEach/$return` object.

You specify an object with two keys, `$forEach: <some list or object>` and `$return: <any value>`. You can also optionally add a `$filter: <expression>` key, which if evaluates to `false` for a particular value, it will be omitted.

Template strings in the `$return` and `$filter` fields are resolved with the same template context as what's available when resolving the for-loop, in addition to `${item.value}` which resolves to the list item being processed, and `${item.key}`.

You can loop over lists as well as mapping objects. When looping over lists, `${item.key}` resolves to the index number (starting with 0) of the item in the list. When looping over mapping objects, `${item.key}` is simply the key name of the key value pair.

Here's an example where we kebab-case a list of string values:

```yaml
kind: Run
variables:
  values:
    - some_name
    - AnotherName
    - __YET_ANOTHER_NAME__
spec:
  args:
    $forEach: ${var.values}
    $return: ${kebabCase(item.value)}
```

Here's another example, where we create an object for each value in a list and skip certain values:

```yaml
kind: Deploy
type: container
variables:
  ports:
    - 80
    - 8000
    - 8100
    - 8200
spec:
  ports:
    # loop through the ports list declared above
    $forEach: ${var.ports}
    # only use values higher than 1000
    $filter: ${item.value > 1000}
    # for each port number, create an object with a name and a port key
    $return:
      name: port-${item.key}  # item.key is the array index, starting with 0
      containerPort: ${item.value}
```

And here we loop over a mapping object instead of a list:

```yaml
kind: Deploy
type: container
variables:
  ports:
    http: 8000
    admin: 8100
    debug: 8200
spec:
  ports:
    # loop through the ports map declared above
    $forEach: ${var.ports}
    # for each port number, create an object with a name and a port key
    $return:
      name: ${item.key}
      containerPort: ${item.value}
```

And lastly, here we have an arbitrary object for each value instead of a simple numeric value:

```yaml
kind: Deploy
type: container
variables:
  ports:
    http:
      container: 8000
      service: 80
    admin:
      container: 8100
    debug:
      container: 8200
spec:
  ports:
    # loop through the ports map declared above
    $forEach: ${var.ports}
    # for each port number, create an object with a name and a port key
    $return:
      name: ${item.key}
      # see how we can reference nested keys on item.value
      containerPort: ${item.value.container}
      # resolve to the service key if it's set, otherwise the container key
      servicePort: ${item.value.service || item.value.container}
```

#### Merging maps

Any object or mapping field supports a special `$merge` key, which allows you to merge two objects together. This can be used to avoid repeating a set of commonly repeated values.

Here's an example where we share a common set of environment variables for two services:

```yaml
kind: Project
variables:
  - commonEnvVars:
      LOG_LEVEL: info
      SOME_API_KEY: abcdefg
      EXTERNAL_API_URL: http://api.example.com
```

```yaml
kind: Deploy
type: container
name: service-a
spec:
  env:
    $merge: ${var.commonEnvVars}
    OTHER_ENV_VAR: something
    LOG_LEVEL: debug  # <- This overrides the value set in commonEnvVars, because it is below the $merge key
---
kind: Deploy
type: container
name: service-b
services:
  env:
    SOME_API_KEY: default # <- Because this is above the $merge key, the API_KEY from commonEnvVars will override this
    $merge: ${var.commonEnvVars}
```

Notice above that the position of the `$merge` key matters. If the keys being merged overlap between the two objects, the value that's defined later is chosen.

#### Optional values

In some cases, you may want to provide configuration values only for certain cases, e.g. only for specific environments. By default, an error is thrown when a template string resolves to an undefined value, but you can explicitly allow that by adding a `?` after the template.

Example:

```yaml
kind: Project
providers:
  - name: kubernetes
    kubeconfig: ${var.kubeconfig}?
```

This is useful when you don't want to provide *any* value unless one is explicitly set, effectively falling back to whichever the default is for the field in question.

### Project variables

A common use case for templating is to define variables in the project/environment configuration, and to use template strings to propagate values to actions in the project.

You can define them in your project configuration using the [`variables` key](/reference/project-config#variables), as well as the [`environment[].variables` key](/reference/project-config#environmentsvariables) for environment-specific values.

You might, for example, define project defaults using the `variables` key, and then provide environment-specific overrides in the `environment[].variables` key for each environment. When merging the environment-specific variables and project-wide variables, we use a [JSON Merge Patch](https://tools.ietf.org/html/rfc7396).

The variables can then be referenced via `${var.<key>}` template string keys. For example:

```yaml
kind: Project
variables:
  log-level: info
environments:
  - name: local
    variables:
      log-level: debug
  - name: remote

---

kind: Deploy
spec:
  env:
    LOG_LEVEL: ${var.log-level}   # <- resolves to "debug" for the "local" environment, "info" for the "remote" env
```

Variable values can be any valid JSON/YAML values (strings, numbers, nulls, nested objects, and arrays of any of those). When referencing a nested key, simply use a standard dot delimiter, e.g. `${var.my.nested.key}`.

You can also output objects or arrays from template strings. For example:

```yaml
kind: Project
variables:
  dockerBuildArgs: [--no-cache, --squash]  # (this is just an example, not suggesting you actually do this :)
  envVars:
    LOG_LEVEL: debug
    SOME_OTHER_VAR: something

---

kind: Build
spec:
  buildArgs: ${var.dockerBuildArgs}  # <- resolves to the whole dockerBuildArgs list

---

kind: Deploy
spec:
  env: ${var.envVars}  # <- resolves to the whole envVars object
```

#### Variable files (varfiles)

You can also provide variables using "variable files" or *varfiles*. These work mostly like "dotenv" files or envfiles. However, they don't implicitly affect the environment of the Garden process and the configured services, but rather are added on top of the `variables` you define in your project configuration (or action variables defined in the `variables` of your individual action configurations).

This can be very useful when you need to provide secrets and other contextual values to your stack. You could add your varfiles to your `.gitignore` file to keep them out of your repository, or use e.g. [git-crypt](https://github.com/AGWA/git-crypt), [BlackBox](https://github.com/StackExchange/blackbox) or [git-secret](https://github.com/sobolevn/git-secret) to securely store the files in your Git repo.

By default, Garden will look for a `garden.env` file in your project root for project-wide variables, and a `garden.<env-name>.env` file for environment-specific variables. You can override the filename for each as well.

To use a action-level varfile, simply configure the `varfile` field to be the relative path (from action root) to the varfile you want to use for that action. For example:

```yaml
# my-deploy/garden.yml
kind: Deploy
name: my-deploy
# Here, we use per-environment action varfiles as an optional override for variables (these have a higher precedence
# than those in the `variables` field below).
#
varfiles:
  # If a varfile is defined but not found, an error is thrown in order to prevent misconfigurations silently passing.
  - my-service.${environment.name}.yaml
  # To add an optional varfile, specify an object with the following properties:
  # - path: The relative path to the varfile from the action root directory.
  # - optional: A boolean value indicating whether the varfile is optional or required.
  - path: my-service-2.${environment.name}.yaml
    optional: true
variables:
  # This overrides the project-level hostname variable
  hostname: my-service.${var.hostname}
  # You can specify maps or lists as variables
  envVars:
    LOG_LEVEL: debug
    DATABASE_PASSWORD: ${var.database-password}
spec:
  ingresses:
    - path: /
      port: http
      # This resolves to the hostname variable set above, not the project-level hostname variable
      hostname: ${var.hostname}
  # Referencing the above envVar action variable
  env: ${var.envVars}
```

Action varfiles must be located inside the action root directory. That is, they must be in the same directory as the action configuration, or in a subdirectory of that directory.

Note that variables defined in action varfiles override variables defined in project-level variables and varfiles (see the section on variable precedence order below).

The format of the files is determined by the configured file extension:

* `.env` - Standard "dotenv" format, as supported by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.yaml`/`.yml` - YAML. Must be a single document in the file, and must be a key/value map (but keys may contain any value types).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

{% hint style="info" %}
The default varfile format will change to YAML in Garden v0.14, since YAML allows for definition of nested objects and arrays.

In the meantime, to use YAML or JSON files, you must explicitly set the varfile name(s) in your project configuration, via the [`varfile`](/reference/project-config#varfile) and/or [`environments[].varfile`](/reference/project-config#environmentsvarfile) fields.
{% endhint %}

You can also set variables on the command line, with `--var` flags. To override a nested variable, you can use dot notation. Note that while this is handy for ad-hoc invocations, we don't generally recommend relying on this for normal operations, since you lose a bit of visibility within your configuration. But here's one practical example:

```sh
# Override three specific variables value and run a task.
# Use dot notation to override nested variables
garden run my-run --var my-run-arg=foo,some-numeric-var=123,my-nested-vars.var1=bar
```

Multiple variables are separated with a comma, and each part is parsed using [dotenv](https://github.com/motdotla/dotenv#rules) syntax.

### Variable precedence order

The order of precedence is as follows (from highest to lowest):

1. Individual variables set with `--var` CLI flags.
2. The module/action-level varfile (if configured).
3. Module/action variables set in `module.variables`.
4. The environment-specific varfile (defaults to `garden.<env-name>.env`).
5. The environment-specific variables set in `environment[].variables`.
6. Configured project-wide varfile (defaults to `garden.env`).
7. The project-wide `variables` field.

{% hint style="warning" %}
Note that [Module variables](https://github.com/garden-io/garden/blob/0.12/docs/features/variables-and-templating.md#module-variables) always take precedence over any of the above, in the context of the module being resolved.
{% endhint %}

When you specify variables in multiple places, we merge the different objects and files using a [JSON Merge Patch](https://tools.ietf.org/html/rfc7396).

Here's an example, where we have some project variables defined in our project config, and environment-specific values—including secret data—in varfiles:

```yaml
# garden.yml
apiVersion: garden.io/v2
kind: Project
...
variables:
  LOG_LEVEL: debug
environments:
  - name: local
    ...
  - name: remote
    ...
```

```
# garden.remote.env
log-level=info
database-password=fuin23liu54at90hiongl3g
```

```yaml
# my-service/garden.yml
kind: Deploy
spec:
  env:
    LOG_LEVEL: ${var.log-level}
    DATABASE_PASSWORD: ${var.database-password}
```

### Provider outputs

Providers often expose useful variables that other provider configs and actions can reference, under `${providers.<name>.outputs.<key>}`. Each provider exposes different outputs, and some providers have dynamic output keys depending on their configuration.

For example, you may want to reference the app namespace from the [Kubernetes provider](/reference/providers/kubernetes) in module configs:

```yaml
kind: Deploy
type: helm
spec:
  values:
    namespace: `${providers.kubernetes.outputs.app-namespace}`
```

Another good example is referencing outputs from Terraform stacks, via the [Terraform provider](/using-garden-with/terraform/configure-provider):

```yaml
kind: Deploy
spec:
  env:
    DATABASE_URL: `${providers.terraform.outputs.database_url}` # <- resolves the "database_url" stack output
```

Check out the individual [provider reference](/reference/providers) guides for details on what outputs each provider exposes.

### Action outputs

Actions often output useful information, that other actions can reference (provider and project configs cannot reference action outputs). Every action also exposes certain keys, like the action version.

For example, you may want to reference the image name and version of a [container Build](/reference/module-types/container):

```yaml
kind: Deploy
type: helm
spec:
  values:
    # Resolves to the image name of the module, with the module version as the tag (e.g. "my-image:abcdef12345")
    image: `${actions.my-build.outputs.deployment-image-id}`
```

Check out the individual [action type reference](/reference/action-types) guides for details on what outputs each action type exposes.

### Action Runtime outputs

Some actions (namely Runs) expose template keys prefixed with `actions.<kind>.<name>.outputs.` which some special semantics. They are used to expose *runtime outputs* from actions and therefore are resolved later than other template strings. *This means that you cannot use them for some fields, such as most identifiers, because those need to be resolved before validating the configuration.*

That caveat aside, they can be very handy for passing information between actions. For example, you can pass log outputs from one task to another:

```yaml
kind: Run
type: exec
name: prep-run
spec:
  command: [echo, "my run output"]
---
kind: Deploy
name: my-deploy
dependencies: [run.prep-run]
spec:
  env:
    PREP_TASK_OUTPUT: ${actions.run.prep-run.outputs.log}  # <- resolves to "my task output"
```

Here the output from `prep-run` is copied to an environment variable for `my-deploy`. *Note that you currently need to explicitly declare `prep-run` as a dependency for this to work.*

For a practical use case, you might for example make a Run that provisions some infrastructure or prepares some data, and then passes information about it to Deploy.

Different action types expose different outputs. Please refer to the [action type reference docs](/reference/action-types) for details.

### Next steps

For a full reference of the keys available in template strings in different contexts, please look at the [Template Strings Reference](/reference/template-strings), as well as individual [providers](/reference/providers) for provider outputs, and [action types](/reference/action-types) for action and runtime output keys.

Also take a look at our [Guides section](https://github.com/garden-io/garden/blob/latest-release/docs/guides/README.md) for various specific uses of Garden.


# Remote Variables and Secrets

### Overview

The Remote Variables feature allows you to store variables and secrets securely in [Garden Cloud](https://app.garden.io) and reference them in your Garden configuration. Remote variables and secrets can be scoped to environments and specific Garden users.

{% hint style="info" %}
This feature requires [Garden version 0.14.10](https://github.com/garden-io/garden/releases/tag/0.14.10) (or newer).
{% endhint %}

Here's a quick example before we dive into the details. Below is a screenshot of secrets stored in Garden Cloud. Notice how the secrets are scoped to different environments and users 👇

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/remote-variables-dark.png" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/remote-variables-light.png" alt="A list of remote variables/secrets"></picture><figcaption><p>A list of remote variables/secrets</p></figcaption></figure>

In your Garden config you can reference the `DB_PASSWORD` remote variable like so:

```yaml
# In project.garden.yml
kind: Project
name: my-project
importVariables:
  - from: garden-cloud
    list: "varlist_abcdef"
---
# In api/garden.yml
kind: Deploy
name: api
type: kubernetes
spec:
  # ...
  env:
    name: DB_PASSWORD
    value: ${imported.DB_PASSWORD}

```

Now, if you run `garden deploy --env ci` (e.g. from a GitHub Action workflow), the `DB_PASSWORD` value will resolve to the value defined for the CI environment.

Similarly, when Lisa and Tionne run `garden deploy`, the value resolves to what's defined for their dev environments.

{% hint style="info" %}
Quick note on terminology: Remote variables can be stored encrypted or in plain text. In what follows we'll generally refer to them as just "variables" or "remote variables" and only as "secrets" if we're specifically referring to encrypted variables.
{% endhint %}

### Quickstart

#### Step 1 — Create a variable list in Garden Cloud

Log into [Garden Cloud](https://app.garden.io) and navigate to the variables page. If you haven't used variables in this organization before, you'll be asked to create your first variable list.

All variables must belong to a variable list. This allows you to import different sets of variables into different projects. We recommend naming the list after your project.

Go ahead and create a list and give it a description.

#### Step 2 — Create remote variables

Next create some variables for the list using the "Create variable" button. You can choose between secret and plain text values and optionally scope them to environments and users.

To scope a variable to an environment, select or create the environment in the pop-up dialog.

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/create-variable-dark.png" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/create-variable-light.png" alt="A list of remote variables/secrets"></picture><figcaption><p>The create variable dialog</p></figcaption></figure>

{% hint style="warning" %}
When scoping a variable to an environment, the environment name MUST match one of the environment names you have in your Garden config (under the project level `environments` field).
{% endhint %}

#### Step 3 — Import the list in your Garden project

After you've created the list and some variables, copy the config snippet from the Variables page and add it to your project level Garden configuration, under `importVariables`. It should look something like this:

```yaml
# In your project configuration
kind: Project
name: my-project
importVariables:
  - from: garden-cloud
    list: varlist_<varlist-id>
    description: The "my-project" variable list.
```

{% hint style="info" %}
Variable lists are identified by their ID rather than name so that you can rename them without breaking your configuration. That's why we recommend adding a description as well. When you copy the config from Garden Cloud the description will be generated for you.
{% endhint %}

#### Step 4 — Test that it works

First, make sure you're logged into Garden Cloud by running the login command from your Garden project:

```
garden login
```

Then verify that Garden can use the variables by running:

```console
garden get remote-variables
```

You can also do `garden get remote-variables -o json` for machine readable output.

You should see the variables just created in the output. If you created plain text variables, you'll see the value as well.

#### Step 5 — Use them in your Garden config

You can now reference the variables you created anywhere in your Garden config with `${imported.<variable-name>}`. For example:

```
MY_VARIABLE: ${imported.MY_VARIABLE}
```

### Managing access with service accounts

{% hint style="danger" %}
Variables that aren't scoped to specific users are accessible to anyone in your organization. Read on to see how to manage access by scoping variables to user and/or service accounts.
{% endhint %}

Remote secrets can contain sensitive values that not everyone in your org should have access to. You can manage access by scoping them to specific users.

A variable scoped to a user can not be used by other users. Variables that are not scoped to users will be accessible to everyone in your Garden Cloud organization. Their values aren't visible if they're encrypted but users can still use them implicitly when running Garden commands.

That's why we recommend creating a service account for secrets that should not be shared. We also recommend using a service account for CI in general, instead of running pipelines as a normal user. Here's how you create a service account and scope a variable/secret to it:

1. Navigate to the Users page in [Garden Cloud](https://app.garden.io) and create a service account. Note that service accounts occupy seats just like any other user in your organization and come with build minutes.
2. Create a new variable on the Variables page and select the service account from the user list in the "create variable" dialog. You can also update existing variables and scope them to the service account. Note that user scoped variables must also be scoped to environments.
3. Create an access token for your service account from the Users page by clicking the "more" button for that user in the user list. Note it down, it's only displayed once.

You can now run Garden commands as this service account (e.g. in CI) with:

```
GARDEN_AUTH_TOKEN=<the-auth-token-you-just-created> garden deploy
```

{% hint style="warning" %}
Note that anyone with admin privileges can create an access token for a given service account.
{% endhint %}

### Usage examples

The examples below assume you've read the Quickstart section above and that the `importVariables` field is already set in your Project configuration.

#### Importing variables from multiple lists

You can import variables from multiple variable lists in a single project. You might e.g. have a list with global variables that are shared across multiple projects and a list with project specific variables.

Variables are merged in the order specified, with later lists taking precedence over earlier ones.

For example:

```
# In your project configuration
kind: Project
name: my-project
importVariables:
  - from: garden-cloud
    list: varlist_<varlist-id>
    description: Global variables shared across multiple projects.
  - from: garden-cloud
    list: varlist_<varlist-id> # <--- In case of conflicts, this takes precedence
    description: The "my-project" variable list.
```

#### Using remote variables in K8s manifests

We generally recommend using the `patchResources` field to override your K8s manifests as needed and this same pattern applies for remote variables. For example, this is how you'd set a remote variable as an environment variable:

```yaml
kind: Deploy
type: kubernetes
name: api
spec:
  manifestFiles: [my-manifests.yml]
  patchResources:
    - name: api # <--- The name of the resource to patch, should match the name in the K8s manifest
      kind: Deployment # <--- The kind of the resource to patch
      patch:
        spec:
          template:
            spec:
              containers:
                - name: api # <--- Should match the container name from the K8s manifest
                  env:
                    DB_PASSWORD: ${imported.DB_PASSWORD} # <--- You can define different values for different environments/users and Garden will resolve to the correct value.
```

For a more complete example of this approach, checkout our [K8s Deploy guide](/using-garden-with/kubernetes/deploy-k8s-resource#overwriting-values)

#### Creating remote variables with the Garden CLI

You can programmatically create remote variables via the Garden CLI.

First, get the variable list ID for the relevant list with. If you've already set the `importVariables` field in your project configuration, you can see the ID there.

You can also get all the variable lists with:

```sh
garden get variable-lists
```

Or `garden get variable-lists -o json` for a machine readable output.

Then create your remote variables with the `create remote-variables` command. For example:

```sh
garden create remote-variables varlist_123 DB_PASSWORD=my-pwd ACCESS_KEY=my-key

```

You can also create multiple variables at a time by passing a file of variables (dot env or JSON format) to the command. To see the different options, run:

```sh
garden create remote-variables --help
```

#### Rotating variables that are about to expire

When creating variables you can optionally set an expiration date. For example if you create an access token in a platform you use with a three month lifetime you can include that information when creating the variable in Garden Cloud.

You can then list all the variables that are about to expire with some `jq` magic (assuming you have `jq` installed):

```sh
garden get remote-variables -o json | jq '.result.variables[]
  | select(.expiresAt != null)
  | select(((.expiresAt | sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601) - now) < (2 * 24 * 60 * 60)
           and ((.expiresAt | sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601) - now) > 0)
  | .id'
```

This will return the IDs of all variables that expire in the next two days in JSON format

You can then remove them with the `delete remote-variables` command:

```sh
garden delete remote-variables <ids from previuous step>
```

...and re-create with updated values with the `garden create variables` command like we used in the [example above](#creating-remote-variables-with-the-garden-cli).


# Config Templates

Config templates are a way to define reusable abstractions for actions or workflows. This provides a powerful yet easy-to-use mechanism to tailor Garden's functionality to your needs, improve governance, reduce boilerplate, and provide higher-level abstractions to application developers.

You can create customized templates for actions and workflows, and render them using `kind: RenderTemplate` resources. These templates allow you to define your own schemas and abstractions, which are then translated at runtime to one or more resources.

Config templates can be defined within a project, or in a separate repository that can be shared across multiple projects (using remote sources).

You can also use [Matrix templates](/features/matrix-templates) to create multiple variations of actions in a compact form.

### How it works

We'll use the [`templated-k8s-container example`](https://github.com/garden-io/garden/blob/latest-release/examples/templated-k8s-container/README.md) to illustrate how templates work. This example has a `k8s-container` template, that generates one `Build` action of type `container` for building an image, and one `Deploy` action of type `kubernetes` for deploying that image. A template like this is useful to customize the Kubernetes manifests for your services, but of course it's just one simple example of what you could do.

The template is defined like this:

```yaml
kind: ConfigTemplate
name: k8s-container
inputsSchemaPath: schema.json

configs:
  - kind: Build
    type: container
    name: ${parent.name}
    description: ${parent.name} image

  - kind: Deploy
    type: kubernetes
    name: ${parent.name}
    description: ${parent.name} manifests

    dependencies:
      - build.${parent.name}

    manifests:
      ...
```

And it's used like this:

```yaml
kind: RenderTemplate
template: k8s-container
name: my-service
inputs:
  containerPort: 8080
  servicePort: 80
```

First off, notice that we have a `kind: ConfigTemplate`, which defines the template, and then a `kind: RenderTemplate` which references and uses the `ConfigTemplate` via the `template` field. You can have any number of instances referencing the same template.

The sections below describe the example in more detail.

#### Defining actions and workflows

Each template can include one or more actions (`Build`, `Deploy`, `Test` or `Run`) or workflows (`kind: Workflow`) under the `configs` key. The schema for each action or workflow is exactly the same as for normal actions or workflows with just a couple of differences:

* In addition to any other template strings available when defining modules, you additionally have `${parent.name}`, `${template.name}` and `${inputs.*}` (more on inputs in the next section). **It's important that you use one of these for the names of the actions, so that every generated action has a unique name.**.
* You can set a `path` field on each config to any subdirectory relative to the directory where the `RenderTemplate` config is placed.

#### Defining and referencing inputs

It's possible to define a schema to validate inputs given to a `ConfigTemplate`. If no schema is defined any inputs are allowed.

On the `ConfigTemplate`, the `inputsSchemaPath` field points to a standard [JSON Schema](https://json-schema.org/) file, which describes the schema for the `inputs` field on every action and module that references the template. In our example, it looks like this:

```json
{
  "type": "object",
  "properties": {
    "containerPort": {
      "type": "integer"
    },
    "servicePort": {
      "type": "integer"
    },
    "replicas": {
      "type": "integer",
      "default": 3
    }
  },
  "required": [
    "containerPort",
    "servicePort"
  ]
}
```

This schema says that the `containerPort` and `servicePort` inputs are required, and that you can optionally set a `replicas` value as well. Any JSON Schema with `"type": "object"` is supported, and users can add any parameters that templated actions and modules should specify. These could be ingress hostnames, paths, or really any flags that need to be customizable per action or module.

These values can then be referenced using `${inputs.*}` template strings, anywhere under the `configs` and `modules` fields.

*Note that special care needs to be taken when using template strings in the `inputs` field in a `RenderTemplate` config. Fields in the resulting configs from the template may need to be resolvable at different times, and using e.g. action references in input values may not work in all cases.*

**Escaping template strings**

Sometimes you may want to pass template strings through when generating files, instead of having Garden resolve them. This could for example be handy when templating a Terraform configuration file which uses a similar templating syntax.

To do this, simply add an additional `$` in front of the template string, e.g. `$${var.dont-resolve-me}`.

#### Action references within a templated action

In many cases, it's important for the different actions in a single template to depend on one another, and to reference outputs from one another. You do this basically the same way as in normal actions, but because action names in a template are generally templated themselves, it's helpful to look at how to use templates in action references.

Here's a section from the manifests in our example:

```yaml
...
      containers:
        - name: main
          image: ${actions.build["${parent.name}"].outputs.deployment-image-id}
          imagePullPolicy: "Always"
          ports:
            - name: http
              containerPort: ${inputs.containerPort}
```

Notice the `image` field above. We use bracket notation to template the action name, whose outputs we want to reference: `${actions.build["${parent.name}"].outputs.deployment-image-id}`. Here we're using that to get the built image ID of the `${parent.name}` Build in the same template.

*Note that for a reference like this to work, that action also needs to be specified as a dependency.*

#### Sharing templates

If you have multiple projects it can be useful to have a central repository containing action and module templates, that can then be used in all your projects.

To do that, simply place your `ConfigTemplate` configs in a repository (called something like `garden-templates`) and reference it as a remote source in your projects:

```yaml
apiVersion: garden.io/v2
kind: Project
...
sources:
  - name: templates
    repositoryUrl: https://github.com/my-org/garden-templates:stable
```

Garden will then scan that repo when starting up, and you can reference the templates from it across your project.

### Further reading

* [Matrix templates](/features/matrix-templates).
* [ConfigTemplate reference docs](/reference/config-template-config).
* [RenderTemplate reference docs](/reference/render-template-config).
* [`templated-k8s-container example`](https://github.com/garden-io/garden/blob/latest-release/examples/templated-k8s-container/README.md).

### Next steps

Take a look at our [Guides section](https://github.com/garden-io/garden/blob/latest-release/docs/guides/README.md) for more of an in-depth discussion on Garden concepts and capabilities.


# Workflows

Workflows allow users to define simple, CI-like sequences of Garden commands and script *steps*, that can be run from a command line, in CI pipelines or directly triggered from PRs or branches using Garden Cloud.

Custom shell scripts can be used for preparation ahead of running Garden commands, handling outputs from the commands, and more.

A sequence of commands executed in a workflow is also generally more efficent than scripting successive runs of Garden CLI commands, since state is cached between the commands, and there is no startup delay between the commands.

{% hint style="warning" %}
As of Garden 0.13, the CLI command to run a Workflow is `garden workflow` instead of `garden run workflow`.
{% endhint %}

## How it Works

Workflows are defined with a separate *kind* of configuration file, with a list of *steps*:

```yaml
# workflows.garden.yml
kind: Workflow
name: my-workflow
steps:
  - ...
```

We suggest making a `workflows.garden.yml` next to your project configuration in your project root. You can also place your workflow definitions in your project root `project.garden.yml`/`garden.yml` file (with a `---` separator after the project configuration).

Each step in your workflow can either trigger Garden commands, or run custom scripts. The steps are executed in succession. If a step fails, the remainder of the workflow is aborted.

You can run a workflow by running `garden workflow <name>`, or have it [trigger automatically](#triggers) via Garden Cloud.

### Command steps

A simple command step looks like this:

```yaml
kind: Workflow
name: my-workflow
steps:
  - command: [deploy] # runs garden deploy
```

You can also provide arguments to commands, and even template them:

```yaml
kind: Workflow
name: my-workflow
steps:
  - command: [run, ${var.task-name}]  # runs a specific task, configured by the `task-name` variable
```

{% hint style="warning" %}
Not all Garden commands can be run in workflows, and some option flags are not available. Please see the [command reference](/reference/commands) to see which commands are supported in workflows.
{% endhint %}

The available keys for templating can be found in the [template reference](/reference/template-strings/workflows).

### Script steps

A script step looks something like this:

```yaml
kind: Workflow
name: my-workflow
steps:
  - script: |
      echo "Hello there!"
```

Scripts can also be templated:

```yaml
kind: Workflow
name: my-workflow
steps:
  - script: |
      echo "Hello ${project.name}!"
```

### Environment variables

To explicitly provide environment variables to the steps of a workflow, you can use the `workflow.envVars` field:

```yaml
kind: Workflow
name: my-workflow
envVars:
  MY_ENV_VAR: some-value
  MY_PROJECT_VAR: ${var.my-var} # Use template strings
  SECRET_ACCESS_TOKEN: ${secrets.SECRET_ACCESS_TOKEN} # Use a Garden Enterprise secret
```

Workflow-level environment variables like this can be useful e.g. for providing templated values (such as secrets or project variables) to several script steps, or to initialize providers in the context of a CI system.

Note that workflow-level environment variables apply to all steps of a workflow (both command and script steps).

### The `skip` and `when` options

By default, a workflow step is run if all previous steps have been run without errors. Sometimes, it can be useful to override this default behavior with the `skip` and `when` fields on workflow steps.

The `skip` field is a boolean. If its value is `true`, the step will be skipped, and the next step will be run as if the skipped step succeeded.

Note that skipped steps don't produce any outputs (see the [step outputs](#step-outputs) section below for more). However, skipped steps are shown in the command log.

The `when` field can be used with the following values:

* `onSuccess` (default): This step will be run if all preceding steps succeeded or were skipped.
* `onError`: This step will be run if a preceding step failed, or if its preceding step has `when: onError`. If the next step has `when: onError`, it will also be run. Otherwise, all subsequent steps are ignored. See below for more.
* `always`: The step will always be run, regardless of whether any previous steps have failed.
* `never`: The step will always be ignored, even if all previous steps succeeded. Note: Ignored steps don't show up in the command logs.

The simplest usage pattern for `onError` steps is to place them at the end of your workflow (which ensures that they're run if any step in your workflow fails):

```yaml
kind: Workflow
name: my-workflow
steps:
  - command: [run, my-task]
  - command: [deploy]
  - command: [test]
  - script: |
      echo "Run if any of the previous steps failed"
    when: onError
  - script: echo "This task is always run, regardless of whether any previous steps failed."
    when: always
```

A more advanced use case is to use `onError` steps to set up "error handling checkpoints" in your workflow.

For example, if the first step (`run my-task`) fails in this workflow:

```yaml
kind: Workflow
name: my-workflow
steps:
  - command: [run, my-task]
  - script: |
      echo "Run if my-task step failed"
    when: onError
  - script: |
      echo "Also run if my-task step failed"
    when: onError
  - command: [deploy]
  - command: [test]
  - script: |
      echo "Run if the deploy or test steps failed"
    when: onError
  - script: | # Finally, an `always` step (for example, to clean up the staging environment)
      echo "This task is always run, regardless of whether any previous steps failed."
    when: always
```

then the first two `onError` steps will be run, and all other steps will be skipped (except for the last one, since it has `when: always`). This can be useful for rollback operations that are relevant only at certain points in the workflow.

You can also template the values of `skip` and `when` for even more flexibility. For example:

```yaml
kind: Workflow
name: my-workflow
steps:
  - script: |
      echo "Fetching credentials for staging environment"
    skip: ${environment.name != "staging"} # This step is only run in the staging environment
  - command: [deploy]
  - script: |
      echo "Run if deploy step failed"
    when: onError
  - script: |
      echo "Also run if deploy step failed"
    when: onError
  - command: [build]
    when: never # This is never run
  - command: [test]
  - script: |
      echo "Run if test step failed, but not if the deploy step failed"
    when: onError
  - script: | # Finally, an `always` step (for example, to clean up the staging environment)
      echo "Clean up staging environment, regardless of whether the workflow succeeded or failed."
    when: "${environment.name == 'staging' ? 'always' : 'never'}"
```

### Step outputs

Workflow steps can reference outputs from previous steps, using template strings. This is particularly useful when feeding command outputs to custom scripts, e.g. for custom publishing flows, handling artifacts and whatever else you can think of.

For example, to retrieve a module version after a build:

```yaml
kind: Workflow
name: my-workflow
steps:
  - command: [build]
  - script: |
      echo "Built version ${steps.step-1.outputs.build.my-build-action.version}"
```

You can also set a `name` on a step, to make it easier to reference:

```yaml
kind: Workflow
name: my-workflow
steps:
  - name: build
    command: [build]
  - name: project-outputs
    command: [get, outputs]
  - script: |
      echo "Project output foo: ${steps.project-outputs.outputs.foo}"
```

The schema of command outputs can be found in the [command reference](/reference/commands). Every step also exports a `log` key for the full command or script log.

### Triggers

Garden Cloud can monitor your project repository for updates, and trigger workflows automatically on e.g. PR and branch updates.

For example, here's how you'd trigger a workflow for PRs made from any `feature/*` branch:

```yaml
kind: Workflow
name: my-workflow
steps:
  - ...
triggers:
  - environment: local
    events: [pull-request]
    branches: [feature/*]
```

For a full description of how to configure triggers, check out the [workflows reference](/reference/workflow-config#triggers).

## Workflows and the Stack Graph

Unlike *actions*, workflows stand outside of the Stack Graph. They cannot currently depend on each other, and nothing in the Stack Graph can reference or otherwise depend on workflows.

## Examples

### Authenticate with Google Cloud before deploying a project

{% hint style="info" %}
Here we use *secrets* (which are a Garden Enterprise feature) for the auth key, but you can replace those template keys with corresponding `${var.*}` or `${local.env.*}` keys as well.
{% endhint %}

```yaml
kind: Workflow
name: deploy
steps:
  - name: gcloud-auth
    description: Authenticate with Google Cloud
    script: |
      export GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcloud-key.json
      echo ${secrets.GCLOUD_SERVICE_KEY} > $GOOGLE_APPLICATION_CREDENTIALS
      gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS
      gcloud --quiet config set project ${var.GOOGLE_PROJECT_ID}
      gcloud --quiet config set compute/zone ${var.GOOGLE_COMPUTE_ZONE}
      gcloud --quiet container clusters get-credentials ${var.GOOGLE_CLUSTER_ID} --zone ${var.GOOGLE_COMPUTE_ZONE}
      gcloud --quiet auth configure-docker
  - name: deploy
    command: [deploy]
```

## Next Steps

Take a look at our [Variables and Templating section](/features/variables-and-templating) for details on how to use templating in your configuration files.

Also check out [Using the CLI](/guides/using-the-cli) for CLI usage examples, and some common day-to-day usage tips.


# Code Synchronization

Garden includes a *sync* mode that allows you to rapidly synchronize your code (and other files) to and from running containers.

The sync mode uses [Mutagen](https://mutagen.io/) under the hood. Garden automatically takes care of fetching Mutagen, so you don't need to install any dependencies yourself to make use of sync mode.

{% hint style="info" %}
This feature used to be called *dev mode* but as of version 0.13 we've opted for more straightforward terminology.\
The functionality is exactly the same as before.
{% endhint %}

### Configuration

{% hint style="warning" %}
Please make sure to specify any paths that should not be synced by setting the provider-level default excludes and/or the `exclude` field on each configured sync! Otherwise you may end up syncing large directories and even run into application errors.
{% endhint %}

To configure a service for sync mode, add `sync` to your Deploy configuration to specify your sync targets:

#### Configuring sync for `container` modules

```yaml
kind: Deploy
name: node-service
type: container
dependencies:
  - build.node-service-build
spec:
  image: ${actions.build.node-service-build.outputs.deploymentImageId}
  args: [ npm, run, serve ]
  sync:
    paths:
      - target: /app/src
        source: src
        mode: two-way
        exclude: [ node_modules ]
...
```

#### Configuring sync for `kubernetes` and `helm` modules

```yaml
kind: Deploy
type: kubernetes # this example looks the same for helm modules (i.e. with `type: helm`)
name: node-service
spec:
  defaultTarget:
    kind: Deployment
    name: vote
  sync:
    paths:
      - containerPath: /app/src
        sourcePath: /src
        mode: two-way
    overrides:
      - command: [ npm, run, dev ]
...
```

### Deploying with sync enabled

To deploy your services with sync enabled, you can use the `deploy` command:

```sh
# Deploy specific services in sync mode:
garden deploy --sync myservice
garden deploy --sync myservice,my-other-service

# Deploy all applicable services with sync enabled:
garden deploy --sync=*
```

Once your deploys are ready, any changes you make that fall under one of the sync specs you've defined will be automatically synced between your local machine and the running service.

Once you quit/terminate the Garden command, the deploys and syncs will keep running in the background. To stop the syncs you can use the `sync stop` command.

### Sync modes

Garden supports several sync modes, each of which maps onto a Mutagen sync mode.

In brief: It's generally easiest to get started with the `one-way` or `two-way` sync modes, and then graduate to a more fine-grained setup based on `one-way-replica` and/or `one-way-replica-reverse` once you're ready to specify exactly which paths to sync and which files/directories to ignore from the sync.

#### `one-way-safe` (or alias `one-way`)

* Syncs a local `source` path to a remote `target` path.
* When there are conflicts, does not replace/delete files in the remote `target` path.
* Simple to use, especially when there are files/directories inside the remote `target` that you don't want to override with the contents of the local `source`.
* On the other hand, if your setup / usage pattern is such that conflicts do sometimes arise for the `source`/`target` pair in question, you may want to use `one-way-replica` instead.

#### `one-way-replica`

* Syncs a local `source` path to a remote `target` path, such that `target` is always an exact mirror of `source` (with the exception of excluded paths).
* When using this mode, there can be no conflicts—the contents of `source` always override the contents of `target`.
* Since conflicts are impossible here, this mode tends to be a better / more reliable choice long-term than `one-way`/`one-way-safe`. However, you may need to configure more fine-grained/specific `source`/`target` pairs and their excludes such that you don't have problems with paths in the remote `target` being overwritten/deleted when they change in the local `source`.

#### `one-way-reverse`

* Same as `one-way`, except the direction of the sync is reversed.
* Syncs a remote `target` path to a local `source` path.
* Has the same benefits and drawbacks as `one-way`: Simple to configure, but conflicts are possible.

#### `one-way-replica-reverse`

* Same as `one-way-replica`, except the direction of the sync is reversed.
* Syncs a remote `target` path to a local `source` path, such that `source` is always an exact mirror of `target` (with the exception of excluded paths).
* When using this mode, there can be no conflicts—the contents of `target` always override the contents of `source`.

#### `two-way-safe` (or alias `two-way`)

* Bidirectionally syncs a local `source` to a remote `target` path.
* Changes made in the local `source` will be synced to the remote `target`.
* Changes made in the remote `target` will be synced to the local `source`.
* When there are conflicts on either side, does not replace/delete the corresponding conflicting paths on the other side.
* Similarly to `one-way`, this mode is simple to configure when there are files in either `source` or `target` that you don't want overridden on the other side when files change or are added/deleted.
* Setting up several `one-way-replica` and `one-way-replica-reverse` syncs instead of `one-way` and `two-way` is generally the best approach long-term, but may require more fine-grained configuration (more sync specs for specific subpaths and more specific exclusion rules, to make sure things don't get overwritten/deleted in unwanted ways).

#### `two-way-resolved`

Same as `two-way-safe` except:

* Changes made in the local `source` will always win any conflict. This includes cases where alpha’s deletions would overwrite beta’s modifications or creations
* No conflicts can occur in this synchronization mode.

In addition to the above, please check out the [Mutagen docs on synchronization](https://mutagen.io/documentation/synchronization) for more info.

#### Notes on Mutagen terminology

Mutagen uses the terminology "alpha" and "beta" for the sync endpoints. In Garden's `one-way`, `one-way-replica` and `two-way` sync modes, alpha is `source` and beta is `target`.

For the reverse sync modes (`one-way-reverse` and `one-way-replica-reverse`), alpha is `target` and beta is `source`.

### Excluding files and directories from syncs

By design, exclusion rules from ignorefiles (such as `.gardenignore` files) are not applied to syncs.

This is done to grant you more control over precisely which files and directories you'd like to sync.

For example, you might want to ignore `dist` or `build` directories in general usage, but still be able to sync them from your local machine to the running container (or from the running container to your local machine). This is easy to achieve with the right configuration.

Exclusion rules can be specified on individual sync configs:

```yaml
kind: Deploy
name: node-service
type: container
dependencies:
  - build.node-service-build
spec:
  image: ${actions.build.node-service-build.outputs.deploymentImageId}
  args: [ npm, run, serve ]
  sync:
    paths:
      - target: /app/src
        source: src
        mode: two-way
        exclude: [ node_modules, tmp, "**/*.log" ] # <------ paths matching these patterns won't be synced
...
```

Project-wide exclusion rules can be set on the `local-kubernetes` and `kubernetes` providers:

```yaml
apiVersion: garden.io/v2
kind: Project
...
providers:
  - name: kubernetes
    ...
    # Configure project-wide exclusion rules and default permission/ownership settings
    # for synced files/directories.
    sync:
      defaults:
        exclude:
          - "/**/node_modules" # <--- with this, we don't have to specify `node_modules` on individual sync specs
```

This is great to reduce repetition in your excludes.

See the reference documentation for the [`kubernetes` provider](/reference/providers/kubernetes#providerssync)) for\
a full list of provider-level options for sync when using the `kubernetes` provider. The same sync options are also\
available when using `local-kubernetes`.

### Permissions and ownership

In certain cases you may need to set a specific owner/group or permission bits on the synced files and directories at\
the target.

To do this, you can set a few options on each sync:

```yaml
kind: Deploy
name: node-service
type: container
dependencies:
  - build.node-service-build
spec:
  image: ${actions.build.node-service-build.outputs.deploymentImageId}
  sync:
    paths:
      - target: /app/src
        source: src
        mode: two-way
        exclude: [ node_modules ]
        defaultOwner: 1000  # <- set an integer user ID or a string name
        defaultGroup: 1000  # <- set an integer group ID or a string name
        defaultFileMode: 0666  # <- set the permission bits (as octals) for synced files
        defaultDirectoryMode: 0777  # <- set the permission bits (as octals) for synced directories
...
```

These options are passed directly to Mutagen. For more information, please see\
the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions).

#### An advanced example

This example demonstrates several of the more advanced options. For more details on the options available, see the\
sections above.

```yaml
apiVersion: garden.io/v2
kind: Project
...
providers:
  - name: kubernetes
    ...
    # Configure project-wide exclusion rules and default permission/ownership settings
    # for synced files/directories.
    sync:
      defaults:
        exclude:
          - "/**/node_modules"
        owner: 1000  # <- set an integer user ID or a string name
        group: 1000  # <- set an integer group ID or a string name
        fileMode: 0666  # <- set the permission bits (as octals) for synced files
        directoryMode: 0777  # <- set the permission bits (as octals) for synced directories

---

kind: Deploy
name: node-service
type: container
description: |
  Here, we sync source code into the remote, and sync back the `test-artifacts` directory
  (populated when we run tests) back to the local machine.
dependencies:
  - build.node-service-build
spec:
  image: ${actions.build.node-service-build.outputs.deploymentImageId}
  args: [ npm, start ]
  sync:
    # Overrides the container's default when the service is deployed in sync mode.
    command: [ npm, run, dev ]
    # You can use several sync specs for the same service. It's generally a good idea to be specific about
    # what you want to sync, and to use `one-way-replica` or `one-way-replica-reverse` when possible to keep
    # things simple and avoid sync conflicts.
    paths:
      - containerPath: /app/src
        sourcePath: /app/src
        # We don't need to exclude `node_modules` here, since above we added a
        # project-wide exclusion rule for that.
        # exclude: [node_modules]
        mode: one-way-replica
      - containerPath: /test-artifacts
        sourcePath: /test-artifacts
        # This syncs back any files/folders  on the remote to the local machine, always
        # overriding the local directory's contents with the remote one. See above for a detailed
        # description of each available sync mode.
        mode: one-way-replica-reverse
...
```

### Troubleshooting

Every so often something comes up in the underlying Mutagen synchronization process, which may not be visible in the\
Garden CLI logs. To figure out what the issue may be (say, ahead of reporting a GitHub issue for Garden), it's useful to\
be able to use the `mutagen` CLI directly.

Because Garden creates a temporary data directory for Mutagen for every Garden CLI instance, you can't use the `mutagen`\
CLI without additional context. However, to make this easier, a symlink to the temporary directory is automatically\
created under `<project root>/.garden/mutagen/<random ID>`, as well as a `mutagen.sh` helper script within that\
directory that sets the appropriate context and links to the automatically installed Mutagen CLI. We also create\
a `<project root>/.garden/mutagen/latest` symlink for convenience.

#### Get list of active syncs

To get the current list of active syncs in an active Garden process, you could run the following from the project root\
directory:

```sh
garden util mutagen sync list
```

#### Restarting sync daemon

Starting from the version `0.13.26`, Garden offers a new file synchronization machinery.\
It is available via the environment variable `GARDEN_ENABLE_NEW_SYNC` and it disabled by default up until version `0.13.32`.

Starting from the version `0.13.34`, the new synchronization machinery is enabled by default.

From version `0.13.44` the old synchronization machinery is completely removed together with the `GARDEN_ENABLE_NEW_SYNC` variable.

It is important to stop all syncs and the sync daemon before changing the value of `GARDEN_ENABLE_NEW_SYNC`, or upgrading to the version `0.13.33` or higher, or downgrading from `0.13.33+` to a lower version. Otherwise, the code synchronization won't work and Garden will fail with an error.

**Switching from the old sync machinery to the new one (Garden `>=0.13.26` and `<=0.13.33`)**

To stop the old sync daemon and to deploy with new sync mode, you need to run the following commands from the project root directory:

```
GARDEN_ENABLE_NEW_SYNC=false garden util mutagen daemon stop
GARDEN_ENABLE_NEW_SYNC=true garden deploy --sync
```

**Switching from the new sync machinery to the old one (Garden `>=0.13.26` and `<=0.13.33`)**

To stop the new sync daemon and to deploy with old sync mode, you need to run the following commands from the project root directory:

```
GARDEN_ENABLE_NEW_SYNC=true garden util mutagen daemon stop
GARDEN_ENABLE_NEW_SYNC=false garden deploy --sync
```

**Switching from the new sync machinery to the old one when downgrading from Garden `>=0.13.44`**

When downgrading, to stop the new sync daemon and to deploy with old sync mode, you need to run the following commands from the project root directory:

```sh
# If you are downgrading to Garden >= 0.13.33
garden util mutagen daemon stop
garden self-update <your-preferred-version>
garden deploy --sync

# If you are downgrading to Garden >= 0.13.26 and <=0.13.32 and want to use the old sync machinery
garden util mutagen daemon stop
garden self-update <your-preferred-version>
GARDEN_ENABLE_NEW_SYNC=false garden deploy --sync

```

**Manually stopping lingering mutagen processes**

If experience any lingering Mutagen processes, you can use the following command to find and kill them:

```sh
kill -9 $(pgrep mutagen)
```


# Custom Commands

As part of a Garden project, you can define *custom commands*. You can think of these like Makefile targets, npm package scripts etc., except you have the full power of Garden's templating syntax to work with, and can easily declare the exact arguments and options the command accepts. The custom commands come up when you run `garden help`, which helps make your project easier to use and more self-documenting.

You'll find more examples and details below, but here's a simple example to illustrate the idea:

```yaml
kind: Command
name: api-dev
description:
  short: Start garden with preconfigured options for API development
steps:
  - name: update-submodules
    exec:
      command:
        - sh
        - -c
        - git submodule update --recursive --remote
  - name: deploy
    gardenCommand:
      - deploy
      - --sync
      - api,worker
      - --log-level
      - debug
      - $concat: ${args.$all}
```

Here we imagine a basic day-to-day workflow for a certain group of developers. The user simply runs `garden api-dev`. The first step updates the submodules in the repo, and then we start `garden deploy` with some parameters that we tend to use or prefer.

Of course this is just an example, but no doubt you can imagine some commands, parameters etc. that you use a lot and which would be nice to codify for you and your team. And this example only uses a fraction of what's possible! Read on for more and see what ideas come up.

### Limitations

Before diving in, there are a few constraints and caveats to be aware of when defining your custom commands:

* For performance reasons, we currently only pick custom commands from the project root folder. They can still be in any `*.garden.yml` file in that directory, much like other configs, but we deliberately avoid scanning the entire project structure for commands. By extension, commands cannot be defined in remote sources at this time.
* Commands cannot have the same name as other Garden commands. This is by design, to avoid any potential confusion for users.
* Only the `exec`, `gardenCommand`, `steps`, and `variables` fields can be templated. Other fields need to be statically defined.

We may later lift some of these limitations. Please post a [GitHub issue](https://github.com/garden-io/garden/issues) if any of the above is getting in your way!

### Overview

Each command has to define a `name`, which must be a valid identifier (following the same rules as action names etc.). A short description must also be provided with `description.short`, and you can also provide a longer description on `description.long` which is shown when you run the command with `--help`. For example:

```yaml
kind: Command
name: api-dev
description:
  short: Short text to show when users run garden help
  long: |
    Some arbitrarily long paragraph that gets into more
    detail and is shown then this command is run with
    the --help flag.
...
```

Then, you must define `steps`, or alternatively `exec` and/or `gardenCommand` for simpler commands.

#### Steps

The `steps` field lets you define a sequence of steps to run, much like Workflow steps. Each step must specify exactly one of `gardenCommand`, `exec`, or `script`:

* **`gardenCommand`**: Runs a Garden command with the given arguments.
* **`exec`**: Runs an external command. Specify `exec.command` and optionally `exec.env`.
* **`script`**: Runs a bash script inline.

Steps run sequentially. If a step fails, subsequent steps are skipped (unless they have `when: onError` or `when: always`). Each step can have a `name` for referencing its outputs in later steps.

#### Legacy: exec and gardenCommand

For simple commands, you can use `exec` and/or `gardenCommand` at the top level. If you specify both, `exec` runs before `gardenCommand`. These fields still work as before, but `steps` is recommended for new commands.

### Referencing outputs between steps

Steps can reference the outputs and logs of previous steps using template strings. Give each step a `name`, then use `${steps.<name>.outputs.*}` or `${steps.<name>.log}` in subsequent steps.

Script steps always produce `stdout`, `stderr`, and `exitCode` outputs. Garden command steps return the command's result object as outputs.

Here's an example that chains steps together:

```yaml
kind: Command
name: preflight
description:
  short: Run preflight checks and deploy if everything passes
steps:
  - name: check-env
    script: |
      if [ -z "$CI" ]; then
        echo "local"
      else
        echo "ci"
      fi
  - name: lint
    exec:
      command: ["npm", "run", "lint"]
  - name: deploy
    gardenCommand:
      - deploy
      - --var
      - environment=${steps.check-env.outputs.stdout}
  - name: notify
    script: echo "Deployed in ${steps.check-env.outputs.stdout} mode"
```

In this example, the `check-env` step detects the environment, `lint` runs a lint check, `deploy` references the detected environment from the first step, and `notify` uses it again to print a message.

#### Error handling

Steps support the same error handling options as Workflow steps:

* **`continueOnError`**: Set to `true` to continue even if the step fails.
* **`when`**: Control when the step runs: `onSuccess` (default), `onError`, `always`, or `never`.
* **`skip`**: Set to `true` (or a template expression) to skip the step entirely.

```yaml
kind: Command
name: safe-deploy
description:
  short: Deploy with rollback on failure
steps:
  - name: deploy
    gardenCommand: ["deploy"]
  - name: rollback
    when: onError
    script: echo "Deploy failed, rolling back..."
  - name: cleanup
    when: always
    script: echo "Cleaning up temporary files..."
```

### Templating

The `exec`, `gardenCommand`, `steps`, and `variables` fields can be templated with many of the fields available for project and environment configuration. See [the reference](/reference/template-strings/custom-commands) for all the fields available.

When your templates reference providers, actions, or modules (e.g. `${actions.deploy.my-service.outputs.*}` or `${providers.kubernetes.outputs.*}`), Garden lazily resolves only what's needed. This means simple commands that don't reference these remain fast, while commands that do can access the full range of runtime data.

Of special note are the `${args.*}` and `${opts.*}` variables. You can [see below](#defining-arguments-and-option-flags) how to explicitly define both positional arguments and option flags, but you can also use the following predefined variables:

* `${args.$all}` is a list of every argument and flag passed to the command (only subtracting the name of the custom command itself). This includes all normal global Garden option flags, as well as the ones you explicitly specify.
* `${args.$rest}` is a list of every positional argument and option that isn't explicitly defined in the custom command, including all global Garden flags.
* `${args["--"]}` is a list of everything placed after `--` in the command line. For example, if you run `garden my-command -- foo --bar`, this variable will be an array containing `"foo"` and `"--bar"`.

You can also reference any provided option flag under `${opts.*}`, even those that are not explicitly defined. Unspecified options won't be validated, but are still parsed and made available for templating.

For example, if you just want to pass all arguments (beyond global options and the command name itself) to a shell script, you can do something like this:

```yaml
kind: Command
name: my-script
description:
  short: Run that script we keep using
steps:
  - script: |
      echo "I'm a super important script, here we go!"
      echo "We're in the ${project.name} project and you are ${local.username}, in case you forgot..."
      ./scripts/foo.sh ${join(args.$rest, ' ')}
```

Here we use the `join` helper function to convert all extra arguments to a space separated string, and pass that to the imagined `foo.sh` script. Pretty much like using `"$@"` in a bash script. We also reference a couple of other common template variables (in this admittedly contrived example...).

### Defining arguments and option flags

You can explicitly define positional arguments and options that are expected or required for your command, using the `args` and `opts` fields. These are validated and parsed before running the command, and are also shown in the help text when running the command with `--help`. For example:

```yaml
kind: Command
name: wrapped
description:
  short: Execute a Run action with arguments and option flags
args:
  - name: action-name
    description: The name of the Run action
    required: true
opts:
  - name: db
    description: Override the database hostname
    type: string
steps:
  - gardenCommand:
      - run
      - ${args.action-name}
      - --var
      - dbHostname=${opts.db || "db"}
```

Here we've made a wrapper command for executing `Run` actions in your project. We require one positional argument for the name of the action to run. Then we define an option for overriding a project variable. For the example, we imagine there's a project variable that's templated into the `Run` actions that controls the hostname of a database they need to connect to. The last lines in the example override the variable and default to `"db"` if the option flag isn't set. To run this command, you could run e.g. `garden wrapped my-action --db test`, which would run `my-action` with the `dbHostname` variable set to `test`.

You might want to augment this example to further accept any additional arguments and append to the Garden command. To do that, you could add the following:

```yaml
...
steps:
  - gardenCommand:
      - run
      - ${args.action-name}
      - --var
      - dbHostname=${opts.db || "db"}
      - $concat: ${args.$rest}  # <- pass any additional parameters through to the command without validation
```

Now you could, for example, run `garden wrapped my-action --db test --force` and the additional `--force` parameter gets passed to the underlying Garden command.

As you can see, you can do a whole lot here! Read on for more examples.

### Using variables

You can specify a `variables` field, and reference those in the `exec`, `gardenCommand`, and `steps` fields using `${var.*}`, similar to action variables. Note that *project variables* are not available, since the Garden project is not resolved ahead of resolving the custom command.


# Remote Sources

You can import **two** types of remote repositories with Garden:

> **Remote&#x20;*****source***: A repository that contains one or more Garden modules or actions *and* their corresponding `garden.yml` config files.

> **Remote&#x20;*****actions***: The source code for a single Garden action. In this case, the `garden.yml` config file is stored in the main project repository while the action code itself is in the remote repository.

The code examples below are from our [remote sources example](https://github.com/garden-io/garden/blob/latest-release/examples/remote-sources/README.md).

## Importing Remote Repositories

### Remote Sources

You can import remote sources via the `sources` directive in the project-level `garden.yml` like so:

```yaml
# examples/remote-sources/garden.yml
apiVersion: garden.io/v2
kind: Project
name: remote-sources
sources:
  - name: web-services
    repositoryUrl: https://github.com/garden-io/garden-example-remote-sources-web-services.git
  - name: db-services
    # use #your-branch to specify a branch, #v0.3.0 for a tag or a full length commit SHA1
    repositoryUrl: https://github.com/garden-io/garden-example-remote-sources-db-services.git#main
```

Note that the URL must point to a specific branch, tag or commit hash.

Use this when you want to import Garden actions from another repository. The repository can contain one or more actions along with their `garden.yml` config files. For example, this is the file tree for the remote `web-services` source:

```sh
# From the root of the garden-example-remote-sources-web-services repository
$ tree .

.
├── README.md
├── result
│   ├── Dockerfile
│   ├── garden.yml
│   └── ...
└── vote
    ├── Dockerfile
    ├── garden.yml
    └── ...
```

You can imagine that this file tree gets merged into the parent project.

If you now run `garden get tests` you will see all the test actions from the remote repositories.

```sh
api-integ
  type: container
  dependencies:
    • Deploy.api
    • Build.api

results-integ
  type: container
  dependencies:
    • Run.db-init
    • Build.result

vote-integ
  type: container
  dependencies:
    • Deploy.vote
    • Build.vote

vote-unit
  type: container
  dependencies:
    • Build.vote
```

### Remote Actions

You can import the source code for a *single* Garden action from another repository via the `source.repository.url` directive in the root-level `garden.yml` like so:

```yaml
# examples/remote-sources/worker/garden.yml
kind: Build
type: container
name: worker
source:
  repository:
    url: https://github.com/garden-io/garden-example-remote-module-jworker.git#0.13
...
```

You can use the `source.path` option together with the `source.repository` option to override the directory inside the git repository.

As with remote sources, the URL must point to a specific branch or tag.

Use this when you want to configure the action within your main project but import the source from another repository.\
In this case, the action in the main project looks like this:

```sh
# examples/remote-sources
$ tree .

.
├── garden.yml
└── worker
    └── garden.yml
```

Notice that it only contains the `garden.yml` file, all the source code is in the [`garden-example-remote-module-jworker`](https://github.com/garden-io/garden-example-remote-module-jworker/) repository. If the remote action also contains a `garden.yml` file it is ignored.

### Local Sources/Actions

You can also import sources from your local file system by setting the `repositoryUrl` or `source.repository.url` to a local file path:

```yaml
# project configuration (remote source)
sources:
  - name: web-services
    repositoryUrl: file:///my/local/project/path#main
```

```yml
# action configuration (remote action)
source:
  repository:
    url: file:///my/local/project/path#main
```

The URL must point to a specific branch or tag.

Local paths work just the same as remote URLs and you'll still need to [link the repository](#linking-remote-sourcesmodules-to-local-code) if you want to edit it locally.

In general we don't recommend using local paths except for testing purposes. The `garden.yml` files should be checked into your version control system and therefore shouldn't contain anything specific to a particular user's setup.

## Linking Remote Sources/Modules to Local Code

If you have a local copy of your external source and want to be able to work on it and make changes, you can use the `link` command. To link the `web-services` source from above, you would run:

```console
garden link source web-services /local/path/to/web-services
```

Now you can edit the local version of the `web-services` repository and it will work just the same as when you edit the main project.

To unlink a remote source use the `unlink` command. For example:

```console
garden unlink source web-services
```

## Updating Remote Sources

Garden will only update a remote source if explicitly asked to do so via the `update-remote` command.

For example, if we had pointed the repository URL of the `web-services` source from above to something like a `main` branch, and we now wanted to pull the latest code from the remote, we would run:

```console
garden update-remote source web-services
```

To update all remote sources and modules, you can run:

```console
garden update-remote all
```

## How it Works

Garden git clones the remote repositories to the `.garden/sources/` directory.

Repositories in `.garden/sources/projects` are handled like any other directory in the main project. They're scanned for `garden.yml` files and the definitions found are synced to the `.garden/build` directory.

In the case of remote actions, Garden first finds the action `garden.yml` file in the main project and then knows to looks for the source code for that action under `./garden/sources/actions`. For builds the code is also synced to the `./garden/build` directory.

Linked sources and actions are handled similarly except Garden uses the local path instead of the `./garden/sources` paths. Additionally, Garden watches the local paths when in watch mode.

Garden keeps track of the repository URL so that it can remove stale sources from the `.garden/sources` directory if the URL changes.


# Matrix templates

You can use a combination of `ConfigTemplate` and `RenderTemplate` configs to create multiple parameterized instances of actions.

Some typical examples would be splitting execution of test suites into segments, or building for multiple platforms or architectures in parallel.

Here's a quick example to illustrate:

```yaml
kind: ConfigTemplate
name: dist

inputs:
  os:
    type: string
  arch:
    type: string

configs:
  - kind: Build
    type: exec
    # Note: ${parent.name} resolves to the name of the RenderTemplate config below
    name: ${parent.name}-${inputs.os}-${inputs.arch}
    spec:
      command: ["./build.sh", "${inputs.os}", "${inputs.arch}"]

---

kind: RenderTemplate
name: dist
template: dist
matrix:
  os: ["linux", "macos"]
  arch: ["amd64", "arm64"]

```

Here we define a `ConfigTemplate` that accepts a couple of different inputs, then we render this template with `RenderTemplate` to create four different actions, one for each combination of `os` and `arch`.

To run all the builds, simply run `garden build`. You could also run specific builds with e.g. `garden build dist-linux-amd64` in this particular example, since a named action is created for each combination of inputs.

The `matrix` field should contain one or more keys, mapping to the specified inputs on the `ConfigTemplate` (which also supports more complex JSON object schemas using the `inputsSchemaPath` field).

Note that you can also supply a single input in the `matrix` field, in which case one action will be created for each value in that array. For example:

```yaml
kind: ConfigTemplate
name: build-image
inputs:
  shard:
    description: A shard number represents a specific 10th of the full test suite
    type: number
configs:
  - kind: Test
    type: container
    name: ${parent.name}-${inputs.shard}
    spec:
      command: ["./test.sh", "--shard", "${inputs.shard}"]

# Render the e2e-test ConfigTemplate 10 times with shards [1, 2, 3, ... 10]
kind: RenderTemplate
name: e2e-test
template: e2e-test
matrix:
  shard: ${range(1, 10)}
```

**Important:** You must make sure that the template inputs are used in the names of the actions under `configs`. Otherwise name clashes will result in a configuration validation error. The above examples illustrate the typical templating (e.g. `${parent.name}-${inputs.os}-${inputs.arch}`).

For more on config templates, please see the [Config Templates guide](/features/config-templates).


# Connecting a Project

{% hint style="info" %}
Connecting a project is only possible for Garden versions 0.14.0 and higher.
{% endhint %}

To use key Garden features such as [team-wide caching](/features/team-caching) and the [Remote Container Builder](/features/remote-container-builder) you need to connect your Garden project to the [Garden Cloud backend](https://app.garden.io).

### Connecting a project

A "connected project" is a Garden project that has an `organizationId` field set in the project level Garden config file.

To connect a project, run the login command from your project directory with:

```
garden login
```

Note that:

* **If this is your first time**, you'll be asked to create an account.
* **If you already have an account and are a part of multiple organizations**, you will be asked to pick the organization this project should belong to.

After you've logged in, **the organization ID will be automatically added to your project level Garden configuration**. You should check these changes into source control. If a project already has an organization ID, nothing will happen.

And that's it!

You can now benefit from team-wide caching and use the Remote Container Builder—and so can other people on your team as long as they're logged in. Note that the container builder needs to be enabled specifically in your config, [see here for more](/using-garden-with/containers/using-remote-container-builder).

See below for how to create an access token so that you can also use team-wide caching and Remote Container Builder in CI.

### Creating personal access tokens

To use Garden in CI you need to create a personal access token and use the `GARDEN_AUTH_TOKEN` environment variable.

You can create the token from the Settings page in [Garden Cloud](https://app.garden.io) and copy it to your clipboard.

<figure><picture><source srcset="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/personal-access-token-dark.png" media="(prefers-color-scheme: dark)"><img src="https://public-assets-for-docs-site.s3.eu-central-1.amazonaws.com/personal-access-token.png" alt="Create and copy personal access token"></picture><figcaption><p>Create and copy personal access token</p></figcaption></figure>

To use the token, run Garden with the `GARDEN_AUTH_TOKEN` set like so:

```console
GARDEN_AUTH_TOKEN=<my-personal-access-token> garden deploy
```

### Offline mode

After you connect your project and set the `organizationId`, you need to remain logged in to use Garden.

If you're not logged in, the command fails. This to prevent degraded performance such as slower builds or missed cache hits that users might not notice, especially in environments like CI.

If you can't log in for some reason, you can use "offline mode" by simply adding the `--offline` flag to your commands or by using the `GARDEN_OFFLINE` environment variable. For example:

```console
garden test --offline
```

...or:

```console
GARDEN_OFFLINE=true garden deploy
```

See also the section above about [creating access tokens](#creating-personal-access-tokens) for environments like CI where you can't run the interactive `login` command.

### Limits

Our free-tier includes a certain amount of build minutes and cache hits/cache retention and you can get more by upgrading to our team or enterprise tiers. You can learn more about the different tiers on our [plans page](https://app.garden.io/plans).


# Environments and Namespaces

Every Garden project has one or more environments that are defined in the project level Garden configuration. Teams often define environments such as `dev`, `ci`, and `prod`.

Each environment can be broken down into several "namespaces", and each Garden run operates in a specific namespace. (This is not to be confused with a Kubernetes Namespace resource, although you will often use the same name for your Garden namespace and your Kubernetes Namespace.)

To specify which Garden namespace to use, you can use either of the following:

* Set a specific namespace using the CLI with the `--env` flag and prepending the namespace to the environment name using the following format `--env <namespace>.<environment>`
* Specify the default namespace in your Garden configuration file, using the [`defaultNamespace`](https://docs.garden.io/guides/pages/MSLyBo40uNb0eDt6hbkM#environments-.defaultnamespace) field under the `environments` specification.

### Using namespaces

You can use namespaces in various ways. Some common use cases include

* **Unique namespaces per developer:** These are typically long-running and belong to the same environment (e.g. `dev`).
* **Ephemeral namespaces for each CI run:** These are deleted after the run completes.
* **Short-lived preview namespaces for each pull request:** These are created when the pull request is opened, updated on every push, and deleted when the pull request is closed.

### An opinionated guide on using namespaces

Below is an opinionated guide on configuring environments and namespaces and the corresponding config.

1. Add any of `dev`, `ci`, `preview` and `prod` environments to your project.
2. For namespaces in the `dev` environment, template in the user’s name.
3. For namespaces in the `ci` environment, template in the build number from your CI runner.
4. For namespaces in the `preview` environment, template in the PR number.
5. Use a deterministic namespace for your `prod` environment.
6. In the `kubernetes` provider config, set `namespace: ${environment.namespace}`. This ensures the Kubernetes namespace corresponds to the Garden namespace.
7. Define your namespace names as variables so that you can, for example, re-use them in hostnames to ensure each instance of your project has a unique hostname.

The example configuration for this setup would look as follows:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
defaultEnvironment: dev
id: <cloud-id>
domain: <cloud-domain>

variables:
  ci-env-name: my-project-ci-${local.env.BUILD_NUMBER || 0} # <--- Depends on your CI provider
  prev-env-name: my-project-preview-${local.env.PR_NUMBER || 0} # <--- Depends on your CI provider
  dev-env-name: my-project-${local.username}

environments:
  - name: ci
    defaultNamespace: ${var.ci-env-name}
    variables:
      hostname: ${var.ci-env-name}.ci.<my-company>.com # <--- Use this in your service config to ensure unique hostnames per instance
  - name: preview
    defaultNamespace: ${var.prev-env-name}
    variables:
      hostname: ${var.prev-env-name}.preview.<my-company>.com
  - name: dev
    defaultNamespace: ${var.dev-env-name}
    variables:
      hostname: ${var.dev-env-name}.dev.<my-company>.com
  - name: prod
    defaultNamespace: my-project
    variables:
      hostname: app.<my-company>.com

providers:
  - name: kubernetes
    namespace: ${environment.namespace} # <--- Ensure the K8s namespace matches the Garden namespace
    defaultHostname: ${var.hostname}
    # ...
```

This allows each developer to get a unique namespace and a unique hostname for each deploy. Some further notes:

* The `dev-env-name` namespace will be something like `my-project-janedoe` so each developer has a unique namespace per project.
* The hostname variable can be re-used in the action configuration. When using the container deploy type, you can e.g. set hostname: `my-service.${var.hostname}` under the [`spec.ingresses[].hostname`](/reference/action-types/deploy/container#specingresseshostname) field. A similar approach can be used for other action types.

This serves as a good base for naming your hostnames and namespaces, but you can tweak it further to meet your specific needs. For example, at Garden we use a similar scheme for our CI and preview environments, but we use the PR or build number as a further unique identifier.


# Installing Garden

This page details the different installation methods for Garden.

Please follow the guide for your operating system:

* [macOS](#macos)
* [Windows](#windows)
* [Linux](#linux)

If you'd like to run Kubernetes locally, please see our [local Kubernetes guide](/guides/install-local-kubernetes)\
for installation and usage information.

If you want to install Garden from source, see the instructions in our [contributor guide](https://github.com/garden-io/garden/tree/main/CONTRIBUTING.md).

## Requirements

You need the following dependencies on your local machine to use Garden:

* Git (v2.14 or newer)

And if you'd like to build and run services locally, you need [a local installation of Kubernetes](https://kubernetes.io/docs/tutorials/hello-minikube/). Garden is committed to supporting [the *latest officially supported* versions](https://kubernetes.io/releases/).\
The information on the Kubernetes support and EOL timelines can be found [here](https://endoflife.date/kubernetes).

## macOS

For Mac, we recommend the following steps to install Garden. You can also follow the manual installation\
steps below if you prefer.

### Step 1: Install Homebrew

If you haven't already set up Homebrew, please follow [their installation instructions](https://brew.sh/).

### Step 2: Install Garden (macOS)

You can easily install Garden using [Homebrew](https://brew.sh) or using our installation script. You may also\
manually download Garden from the [releases page](https://github.com/garden-io/garden/releases) on GitHub.

#### Homebrew

```sh
brew tap garden-io/garden
brew install garden-cli
```

To later upgrade to the newest version, simply run `brew update` and then `brew upgrade garden-cli`.

#### Installation script (macOS)

First make sure the [requirements](#requirements) listed above are installed. Then run our automated installation script:

```sh
curl -sL https://get.garden.io/install.sh | bash
```

To later upgrade to the latest version, simply run the script again.

#### Manual download and install (macOS)

If you prefer, you can perform the installation manually, as follows:

1. Make sure the [requirements](#requirements) listed above are installed.
2. Visit the Garden [releases page](https://github.com/garden-io/garden/releases) on GitHub and download the macOS archive (under *Assets*).
3. Next create a `~/.garden/bin` directory, and extract the archive to that directory. *Make sure to include the whole contents of the archive.*
4. Lastly, either add the `~/.garden/bin` directory to your PATH, or add a symlink from your `/usr/local/bin/garden` to the binary at `~/.garden/bin/garden`.

### Step 3 (optional): Docker and local Kubernetes

To install Docker, Kubernetes and kubectl, we recommend Docker for Mac.

Please refer to their [installation guide](https://docs.docker.com/engine/installation/) for how to download and install it (which is a pretty simple process).

If you'd like to use a local Kubernetes cluster, please refer to the [Local Kubernetes guide](/using-garden-with/kubernetes/local-kubernetes)\
for further information. For remote clusters, take a look at the [Remote Kubernetes guide](/using-garden-with/kubernetes/remote-kubernetes).

## Windows

You can run Garden on Windows 10 or later.

*Note: Building docker images generally requires installing Docker Desktop. Please refer to* [*the Docker Desktop documentation for its requirements*](https://docs.docker.com/desktop/setup/install/windows-install/)*.*

To install the Garden CLI and its dependencies, please use our installation script. To run the script, open PowerShell as an administrator and run:

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/garden-io/garden/main/support/install.ps1'))
```

The things the script will check for are the following:

* The [Chocolatey](https://chocolatey.org) package manager. The script installs it automatically if necessary.
* *git*. The script will install or upgrade those via Chocolatey.

To later upgrade to the newest version, simply re-run the above script.

We also recommend adding an exclusion folder for the `.garden` directory in your repository root to Windows Defender:

```powershell
Add-MpPreference -ExclusionPath "C:\Path\To\Your\Repo\.garden"
```

This will significantly speed up the first Garden build of large projects on Windows machines.

Note that you must run Powershell with elevated permissions when you execute this command.

## Linux

### Step 1: Install core dependencies

Use your preferred method or package manager to install `git`. On Ubuntu, that's `sudo apt install git`, on Alpine `apk add --no-cache git`

The Alpine linux distribution also requires `gcc` to be installed: `apk add --no-cache gcc`.

### Step 2: Install Garden

#### Installation script (Linux)

You can use our installation script to install Garden automatically:

```sh
curl -sL https://get.garden.io/install.sh | bash
```

To later upgrade to the latest version, simply run the script again.

#### Manual download and install (Linux)

If you prefer, you can perform the installation manually, as follows:

1. Visit the Garden [releases page](https://github.com/garden-io/garden/releases) on GitHub and download the linux archive (under *Assets*).
2. Next create a `~/.garden/bin` directory, and extract the archive to that directory. *Make sure to include the whole contents of the archive.*
3. Lastly, either add the `~/.garden/bin` directory to your PATH, or add a symlink from your `/usr/local/bin/garden` to the binary at `~/.garden/bin/garden`.

### Step 3 (optional): Local Kubernetes

If you'd like to use a local Kubernetes cluster, please refer to the [local Kubernetes guide](/using-garden-with/kubernetes/local-kubernetes)\
for installation and usage information.

## Using Garden with proxies

If you're running Garden behind a firewall, you may need to use a proxy to route external requests. To do this,\
you need to set the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables. For example:

```sh
export HTTP_PROXY=http://localhost:9999               # <- Replace with your proxy address.
export HTTPS_PROXY=$HTTP_PROXY                        # <- Replace if you use a separate proxy for HTTPS.
export NO_PROXY=local.demo.garden,localhost,127.0.0.1  # <- This is important! See below.
```

The `NO_PROXY` variable should include any other hostnames you might use for local development, since you likely\
don't want to route local traffic through the proxy.

## Updating Garden

Once you've installed Garden, you can update it with the Garden `self-update` command like so:

```console
garden self-update
```

To install Garden at a specific version, say 0.13.22, you can run:

```
garden self-update 0.13.22
```

To install the latest edge release of Garden Cedar you can run:

```
garden self-update edge-cedar
```

You can learn more about the different options by running:

```
garden self-update --help
```


# Including/Excluding files

By default, all directories under the project root are scanned for Garden actions. Depending on the action kind and type, files in the same directory as the action configuration file might be included as source files for that action. Often, you need more granular control over the context, not least if you have multiple actions in the same directory.

Garden provides three different ways to achieve this:

1. The `scan.include` and `scan.exclude` fields in *project* configuration files.
2. The [".ignore" file](#ignore-file), e.g. `.gitignore` or `.gardenignore`.
3. The `include` and `exclude` fields on [individual actions](#including-and-excluding-files-in-individual-actions).

### Including and excluding files across the project

By default, all directories under the project root are scanned for Garden actions, except those matching your ignore files. You may want to limit the scope, for example if you only want certain actions as part of a project, or if all your actions are contained in a single directory (in which case it is more efficient to scan only that directory).

The `scan.include` and `scan.exclude` fields are a simple way to explicitly specify which directories should be scanned for actions. They both accept a list of POSIX-style paths or globs. For example:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
scan:
  include:
    - actions/**/*
  exclude:
    - actions/tmp/**/*
...
```

Here we only scan the `actions` directory, but exclude the `actions/tmp` directory.

If you specify a list with `include`, only those patterns are included. If you then specify one or more `exclude` patterns, those are filtered out of the ones matched by `include`. If you *only* specify `exclude`, those patterns will be filtered out of all paths in the project directory.

The `scan.exclude` field is also used to limit the number of files and directories Garden watches for changes while running. Use that if you have a large number of files/directories in your project that you do not need to watch, or if you are seeing excessive CPU/RAM usage. The `scan.include` field has no effect on which paths Garden watches for changes.

### .ignore file

{% hint style="info" %}
Generally, using `.gardenignore` files is far more performant than exclude config statements and will decrease graph resolution time.
{% endhint %}

By default, Garden respects `.gardenignore` files and excludes any patterns matched in those files. You can place the ignore files anywhere in your repository, much like `.gitignore` files, and they will follow the same semantics.

You can use those to exclude files and directories across the project, *both from being scanned for Garden modules and when selecting source files for individual actions*. For example, you might put this `.gardenignore` file in your project root directory:

```gitignore
node_modules
public
*.log
```

This would cause Garden to ignore `node_modules` and `public` directories across your project/repo, and all `.log` files.

Note that *these take precedence over both `scan.include` fields in your project config, and `include` fields in your module configs*. If a path is matched by one of the ignore files, the path will not be included in your project or modules.

{% hint style="warning" %}
Prior to Garden `0.13`, it was possible to specify *multiple* ".ignore" files using the [`dotIgnoreFiles`](/reference/project-config#dotIgnoreFiles) field in a project configuration:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
dotIgnoreFiles: [.gardenignore, .gitignore]
```

This behaviour was changed in Garden `0.13`.
{% endhint %}

You can override which filename to use as a *single* ".ignore" file using the [`dotIgnoreFile`](/reference/project-config#dotIgnoreFile) field in your project configuration:

```yaml
apiVersion: garden.io/v2
kind: Project
name: my-project
dotIgnoreFile: .gardenignore
```

The default value of `dotIgnoreFile` is `.gardenignore`.

### Including and excluding files in individual actions

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:

```yaml
kind: Build
description: My container
type: container
include:
  - Dockerfile
  - my-sources/**/*.py
exclude:
  - my-sources/tmp/**/*
```

{% hint style="info" %}
Generally, using `.gardenignore` files is far more performant than exclude config statements and will decrease graph resolution time.
{% endhint %}

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](/reference/project-config) 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.

{% hint style="warning" %}
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.
{% endhint %}

### Git submodules

If you're using Git submodules in your project, please note the following:

1. You may ignore submodules using .ignore files and include/exclude filters. If a submodule path *itself* (that is, the path to the submodule directory, not its contents), matches one that is ignored by your .ignore files or exclude filters, or if you specify include filters and the submodule path does not match one of them, the module will not be scanned.
2. Include/exclude filters (both at the project and module-level) are applied the same way, whether a directory is a submodule or a normal directory.
3. *.ignore files are considered in the context of each git root*. This means that a .ignore file that's outside of a submodule will be completely ignored when scanning that submodule. This is by design, to be consistent with normal Git behavior.


# Installing Local Kubernetes

### Docker Desktop

[Docker Desktop](https://docs.docker.com/engine) is our recommended option for local Kubernetes on Mac and Windows.

Please refer to their [installation guide](https://docs.docker.com/engine/installation/) for how to download and install it (which is a pretty simple process).

*Note: If you have an older version installed, you may need to update it in order to enable Kubernetes support.*

Once installed, open Docker Desktop's preferences, go to the Kubernetes section, tick `Enable Kubernetes` and save.

### MicroK8s

Garden can be used with [MicroK8s](https://microk8s.io) on supported Linux platforms.

To install it, please follow [their instructions](https://microk8s.io/docs/).

Once installed, you need to add the `microk8s` configuration to your `~/.kube/config` so that Garden knows how to access your cluster. We recommend exporting the config like this:

```sh
microk8s config > $HOME/.kube/microk8s.config
```

And then adding this to your `.bashrc`/`.zshrc`:

```sh
export KUBECONFIG=$HOME/.kube/microk8s.config:${KUBECONFIG:-$HOME/.kube/config}
```

You also need to ensure microk8s commands can be run by the user that's running Garden, so that Garden can get its status and enable required extensions if necessary. To do this, add your user to the `microk8s` group:

```sh
sudo usermod -a -G microk8s $USER   # or replace $USER with the desired user, if it's not the current user
```

Note that in-cluster building is currently not supported with microk8s clusters.

### minikube

minikube is a tool that makes it easy to run Kubernetes locally for local development. Garden supports running minikube on macOS, Linux, and Windows via the Windows Subsystem for Linux.

If you wish to use minikube with Garden's image building capabilities, be sure to configure Garden appropriately before running `garden deploy` or `garden build`. See the following sections for more information.

#### Expose minikube's Docker daemon for local image building

minikube runs its own Docker daemon. Practically speaking, this has the effect of isolating images from `garden` when using `garden deploy` or `garden build`. If you receive an error like `Error deploying deploy.backend2: ImagePullBackOff - Back-off pulling image "backend2:v-aa19766a21"`, you'll need to expose minikube's Docker daemon, run the following command:

{% tabs %}
{% tab title="macOS" %}

```sh
eval $(minikube docker-env)
```

{% endtab %}

{% tab title="Linux" %}

```sh
eval $(minikube docker-env)
```

{% endtab %}

{% tab title="Windows" %}

```powershell
& minikube -p minikube docker-env --shell powershell | Invoke-Expression
```

{% endtab %}
{% endtabs %}

If you're using an external image registry, see the following section.

#### minikube and external registries

If you are working in a team and need to use an external registry, you can [configure Garden with an external image registry](https://docs.garden.io/kubernetes-plugins/remote-k8s/configure-registry) such as ECR. Alternatively, you can enable minikube's `registry-creds` addon, by following these steps:

1.Make sure minikube is running by typing `minikube start`

2.Then run minikube `addons configure registry-creds`

3.Select applicable container registry

4.Enter credentials

5.Make sure you run minikube `addons enable registry-creds`

minikube should now be able to authenticate with your chosen cloud provider.

### kind

For kind installation instructions, see the [official docs](https://kind.sigs.k8s.io/docs/user/quick-start/).

To use `kind` with Garden you may need to start your cluster with extra port mappings to allow ingress controllers to run (see [their docs](https://kind.sigs.k8s.io/docs/user/ingress/) for more info):

```sh
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
EOF
```

Alternatively, if you don't need an ingress controller, you can set `setupIngressController: null` in your `local-kubernetes` provider configuration and start the cluster without the above customization.

Note that in-cluster building is currently not supported with kind clusters.

### k3s

Use this command to install k3s so it is compatible with Garden. This command configures k3s to use docker as the container runtime and disables the traefik ingress controller. It also makes the kubeconfig user-accessible and sets the kubernetes context as the current one via the `KUBECONFIG` variable.

```bash
curl -sfL https://get.k3s.io | sh -s - --docker --disable=traefik --write-kubeconfig-mode=644
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
```

### Rancher Desktop

Follow the [official instructions](https://docs.rancherdesktop.io/getting-started/installation/) to install Rancher Desktop for your OS.\
Once installed open "Preferences" in the Rancher Desktop UI. In the "Container Engine" section choose dockerd and in the "Kubernetes" section untick the box that says "Enable Traefik".

{% hint style="warning" %}
If, on deploy, you encounter `error: Internal error occurred: error executing command in container: http: invalid Host header`, please downgrade your Kubernetes version to v1.27.2. This is an [upstream bug in Moby](https://github.com/moby/moby/issues/45935).
{% endhint %}

![Preferences in Rancher Desktop to downgrade Kubernetes version](https://github.com/garden-io/garden/assets/59834693/aaa3f477-ed6f-430a-85f8-f880a96c4f2a)

### k3d

[K3d](https://k3d.io) is a lightweight wrapper to run k3s in containers. Its image registry also runs as a container. To expose it to Garden, you need to map the registry port to the host. The following commands will create a k3d cluster with the name k3d-k3s-default and with the registry exposed on port 12345.

```shell
k3d registry create myregistry.localhost --port 12345

k3d cluster create \
  --agents 1 \
  --k3s-arg "--disable=traefik@server:0" \
  --registry-use k3d-myregistry.localhost:12345 \
  --wait
```

In your `project.garden.yml` file, add the following configuration under your `local-kubernetes` provider\` block:

```yaml
    context: k3d-k3s-default
    deploymentRegistry:
      hostname: k3d-myregistry.localhost
      port: 12345
      insecure: true
      namespace: ${kebabCase(local.username)}
```

### OrbStack

[OrbStack's native Kubernetes offering](https://docs.orbstack.dev/kubernetes/) works seamlessly with Garden. Follow OrbStack's official instructions [to spin up its native Kubernetes cluster](https://docs.orbstack.dev/kubernetes/).

### A note on networking for k3s, k3d and Rancher Desktop

K3s and its derivatives use the [Service Load Balancer](https://docs.k3s.io/networking#service-load-balancer) (ServiceLB) as a LoadBalancer controller. ServiceLB is ingress controller agnostic. By default, Garden installs an NGINX ingress controller to expose domains on common ports.

On macOS and Windows, Rancher Desktop creates a bridged network to serve local domain URLs. This means that you can access your local domains on the host machine. Note that you need to [allow administrative access](https://docs.rancherdesktop.io/ui/preferences/application/general/#administrative-access) for rancher-desktop in order for this to work.

For users of k3d on macOS or Linux you'll need to do some extra configuration to expose your local domains.

You can direct your ingress domain to the IP of the VM by adding an entry to the `/etc/hosts` file on your computer. Use the following command:

```bash
echo "$(kubectl get node/lima-rancher-desktop -o json | jq -r '.status.addresses[] | select(.type=="InternalIP").address') vote.local.demo.garden" | sudo tee -a /etc/hosts
```

Replace `vote.local.demo.garden` with the domain you want to use.

For users of Rancher Desktop users *on Linux* you'll need to port forward the NGINX ingress controller to access your local domains. Use the following command:

```bash
kubectl port-forward --namespace=garden-system service/garden-nginx-ingress-nginx-controller 8080:80
```

Then you can access your local domains on port 8080. For example, `http://vote.local.demo.garden:8080`.

See also Rancher Desktop's [Setup NGINX Ingress Controller](https://docs.rancherdesktop.io/how-to-guides/setup-NGINX-Ingress-Controller/) for more information.

#### Using an alternative ingress controller

If you prefer to use the Traefik ingress controller included with k3s distributions, you must modify the installation instructions for [Rancher Desktop](#rancher-desktop) and [k3d](#k3d) by removing any parts where Traefik is disabled. In your Garden project configuration file, set `setupIngressController: false`. Additionally, apply one of the two methods described above, specifying Traefik's service in the second approach.

### Updating or removing the Garden installed Nginx ingress controller

Garden will not automatically try to update the nginx ingress controller. To update it you must remove it first and then run a Garden command against that cluster again. Garden will then deploy the version of the ingress controller shipped with that specific Garden version. If you want to remove it alltogether, set `setupIngressController: false` in your Garden project's provider configuration.\
To remove the ingress controller run this command:

```
garden plugins kubernetes uninstall-garden-services
```

### Moving between Rancher Desktop and Docker Desktop

If you wish to move from Rancher Desktop to Docker Desktop, or vice versa, you will need to follow a few steps:

1. Uninstall either Rancher Desktop or Docker Desktop.
2. Delete or back up your `~/.kube` directory. This is especially important for Windows users because Docker Desktop treats the `~/.kube` directory as a symlink.
3. Delete or back up your `~/.docker` directory. Docker Desktop sets entries in the `~/.docker/config.json` file that expect Docker Desktop to be running. If you don't delete this file, you will get errors when you try to run `docker` build commands.


# Migrating from Docker Compose to Garden

If you already have an application configured to use Docker Compose and want to migrate it to Garden, you can do so by adding the necessary Garden config files. In this guide, we'll walk through an example of converting a simple Docker Compose project to Garden. You can follow along with the example, or substitute with your own Docker Compose project where relevant.

## Prerequisites

To follow along, you should have:

* Basic familiarity with [Garden](/getting-started/basics) and [Sync mode](/features/code-synchronization)).
* [Docker Desktop](https://www.docker.com/products/docker-desktop/) running locally.
* A local Kubernetes cluster running inside Docker Desktop.
* A project that currently uses Docker Compose (or follow along using the provided example).

## Getting the example application

Clone our [example Docker Compose application](https://github.com/garden-io/garden-docker-compose) and take a look around. In summary, our application is built with a backend (Express), a frontend (React), and a database (MongoDB).

The frontend and backend applications each have their own `Dockerfile`, and there is a top-level `docker-compose.yml` file to tie them together and to add MongoDB.

This application is based on the one at <https://github.com/docker/awesome-compose/tree/master/react-express-mongodb>. We've added four `*.garden.yml` files, which we'll walk through in detail.

### The `project.garden.yml` file

In the root of the directory, we've added `project.garden.yml` with the following contents:

```yaml
apiVersion: garden.io/v2
kind: Project
name: compose2garden

environments:
  - name: default
    variables:
      base-hostname: compose2garden.local.demo.garden

providers:
  - name: local-kubernetes
```

This is a `Project` level file. We call it `compose2garden` in our example, but you can use your own name. We configure a single environment and specify the hostname where we can visit the running application. Finally, we configure `local-kubernetes` (e.g. a Kubernetes cluster running in Docker Desktop) as our provider.

### The `backend/backend.garden.yml` file

For our `backend` application, we've added another Garden configuration file:

```yaml
kind: Build
apiVersion: garden.io/v2
name: backend
description: The backend server image
type: container

---
kind: Deploy
apiVersion: garden.io/v2
name: backend
description: The backend server container
type: container
dependencies:
  - build.backend
  - deploy.mongo
spec:
  image: ${actions.build.backend.outputs.deploymentImageId}
  sync:
    paths:
      - source: ./
        target: /usr/src/app
        mode: "one-way-replica"
  ports:
    - name: http
      containerPort: 3000
  healthCheck:
    httpGet:
      path: /api
      port: http
  ingresses:
    - path: /
      port: http
      hostname: backend.${var.base-hostname}
```

A `Build` action and a `Deploy` action are defined. Make note of the `Deploy` action and it's configuration.

Under `sync` we set up syncing from the action root to the `app` folder on the container, so we can synchronize code changes live when in `sync` mode.

Under `ports` we specify the same port as in our Docker Compose file (`3000`).

We set up a health check for the `/api` route, and an ingress on a subdomain. In our case, this will let us access our `backend` application on `compose2garden.local.demo.garden`.

Finally, we specify the dependency on the `mongo` `Deploy` action, which we will define in a bit.

### The `frontend/frontend.garden.yml` file

For the `frontend` application we create separate Garden configuration file:

```yaml
kind: Build
apiVersion: garden.io/v2
name: frontend
description: The frontend server and UI components image
type: container
exclude:
  - node_modules/**/*

---
kind: Deploy
apiVersion: garden.io/v2
name: frontend
description: The frontend server and UI components container
type: container
dependencies:
  - build.frontend
  - deploy.backend
spec:
  image: ${actions.build.frontend.outputs.deploymentImageId}
  env:
    DANGEROUSLY_DISABLE_HOST_CHECK: true
  sync:
    paths:
      - source: ./src
        target: /usr/src/app/src
        mode: "one-way-replica"
  ports:
    - name: http
      containerPort: 3000
  healthCheck:
    httpGet:
      path: /
      port: http
  ingresses:
    - path: /
      port: http
```

This is similar to the `backend` application, but we specify the `backend` deployment as a dependency, which makes the database (`mongo`) an indirect dependency.

### The `mongo/mongo.garden.yml` file

Here we've created a `mongo` folder, as it did not exist in our original Docker Compose project. The folder contains only the Garden configuration file:

```yaml
kind: Deploy
apiVersion: garden.io/v2
description: MongoDB for storing todo items
type: container
name: mongo

spec:
  image: mongo:4.2.0
  volumes:
    - name: data
      containerPath: /data/db
  ports:
    - name: db
      containerPort: 27017
```

This specifies the same volume and port that we previously specified in Docker Compose.

## Deploying the Garden project to Kubernetes

To build and deploy your project run `garden deploy`. Once this has completed, you'll have the example "To Do" application running on your local Kubernetes cluster.

![To Do](/files/MLX86vbZrc6RGil270wA)

Use `frontend` application's ingress URL from the console output to open the application.

## Running the Garden project in code synchronization mode

You can also try out [live code synchronization](/features/code-synchronization) with Garden.

Just run:

```bash
garden deploy --sync
```

in the project folder. Garden will start up locally. You will see output in your terminal showing that this worked successfully.

Now try to modify some files in `backend` or `frontend` applications. The code changes will be synced to the running applications.

## Larger migrations

This is a basic example but it should give you what you need to migrate larger projects too. If you have feedback on how we could make migrating from Docker Compose easier, please send it our way via [GitHub issues](https://github.com/garden-io/garden/issues) or reach out on [Garden Discussions](https://github.com/garden-io/garden/discussions).


# Using the CLI

Here, we'll describe at a high level the common day-to-day usage of the Garden CLI, with specific examples.

## CLI introduction

The `garden` CLI is how you work with Garden in most scenarios, during development and in CI pipelines. It features a fairly large number of commands, so we'll list the most common ones below. You can run `garden --help` to list them, and use `garden <command> --help` to learn more about individual commands, arguments, option flags, usage examples etc. You can also find a full reference [here](/reference/commands).

If you've not installed the CLI yet, please check out the [installation guide](/guides/installation).

Most of the examples below assume that you've already defined a Garden project.

{% hint style="warning" %}
It is currently not advisable to run multiple `dev`, `build`, `deploy` or `test` commands in parallel because they may interfere with each other. It is fine, however, to run one of those and then run other commands to the side, such as `garden logs`. We plan on improving this in the future.
{% endhint %}

### Common option flags

Every Garden command supports a common set of option flags. The full reference can be found [here](/reference/commands#global-options), but here are the most important ones:

* `--env` sets the environment (and optionally namespace) that the command should act on. Most Garden commands only act on a specific environment, so in most cases you'll specify this, unless you're working on the default environment for the project. See [here](/guides/namespaces) for more about environments and namespaces.
* `--log-level` / `-l` sets the log level. Use e.g. `-l=debug` to get debug logs for the command.
* `--output` / `-o` sets the output format. Use this to get structured output from the commands. `--output=json` outputs JSON, and `--output=yaml` outputs YAML. The structure of the outputs is documented in [the reference](/reference/commands) for most commands.

All option flags can be specified with a space or a `=` between the flag and the value.

## `Deploy` actions

### Deploying all `Deploy`s in a project

This deploys all `Deploy` actions to the default environment and namespace.

```sh
garden deploy
```

### Deploying all `Deploy`s in a project to a non-default environment and namespace

This deploys all `Deploy` actions to `my-namespace` in the `dev` environment.

```sh
garden deploy --env my-namespace.dev
```

### Deploying a single `Deploy`

```sh
garden deploy my-deploy
```

### Deploying more than one specific `Deploy`

When arguments accept one or more actions we space-separate the names.

```sh
garden deploy deploy-a deploy-b
```

### Deploying a `Deploy` with sync enabled

See the [Code synchronization guide](/features/code-synchronization) for more information on how to configure and use syncing for rapid iteration on `Deploy`s.

```sh
garden deploy my-deploy --sync=*
```

### Executing a command in a running `Deploy` container

```sh
garden exec my-deploy -- <command>
```

### Executing an interactive shell in a running `Deploy` container

*Note: This assumes that `sh` is available in the container.*

```sh
garden exec my-deploy -- sh
```

### Getting the status of your `Deploy`s

```sh
garden get status
```

### Getting the status of your `Deploy`s in JSON format

This is suitable for parsing with e.g. the `jq` utility.

```sh
garden get status --output=json  # or `-o json` for short
```

### Stopping all running `Deploys`s

This removes all running `Deploy` actions in `my-namespace` in the `dev` environment.

```sh
garden cleanup env --env=my-namespace.dev
```

### Stopping a single running `Deploy`

```sh
garden cleanup deploy my-deploy
```

## `Test` actions

### Running all tests in a project

```sh
garden test
```

### Running a specific test and attaching

This is handy for running a single test and streaming the log outputs (`garden test`, in comparison, is more meant to run multiple ones or watch for changes, and is less suitable for getting log output).

```sh
garden test my-test -i
```

## `Run` actions

### Running a specific `Run` action

```sh
garden run my-run-action
```

## `Build` actions

### Building all `Build`s

```sh
garden build
```

### Building all `Build`s, forcing a rebuild

```sh
garden build --force  # or -f for short
```

### Building a specific `Build`

```sh
garden build my-build
```

## Workflows

### Running a workflow

Runs `my-workflow` in `my-namespace` in the `dev` environment.

```sh
garden workflow my-workflow --env=my-namespace.dev
```

## Logs

### Retrieving the latest logs for all `Deploy`s

```sh
garden logs
```

### Retrieving the latest logs for a single `Deploy`

```sh
garden logs my-deploy
```

### Stream logs for a `Deploy` action

```sh
garden logs my-deploy --follow  # or -f for short
```

## garden dev

The `garden dev` command runs the Garden interactive development console.\
In that console you can execute Garden commands in interactive mode, like `build`, `deploy`, `run`, `test` and others.\
To see the full list of available commands execute the `help` command in the development console.

### Running interactive development console

```sh
garden dev
```

## Sync mode

For rapid iteration on a running `Deploy` action, you can use a feature called *sync mode*.\
See the [Code synchronization guide](/features/code-synchronization) for details on how to configure and use that feature.

## Project outputs

[Project outputs](https://docs.garden.io/guides/pages/MSLyBo40uNb0eDt6hbkM#outputs\[]) are a handy way to extract generated values from your project.

### Printing project outputs

```sh
garden get outputs
```

### Getting project outputs in JSON format

This you can use to parse in scripts, e.g. using `jq`.

```sh
garden get outputs --output=json  # or `-o json` for short
```

You can also output in YAML with `--output=yaml`.

## Creating new configs

### Creating a new project

This bootstraps a boilerplate `garden.yml` with a project definition in the current directory, and a `.gardenignore` file.

```sh
garden create project
```

### Creating actions

See the [Garden basics guide](/getting-started/basics) to learn more about actions and how to create them.

## Remote sources

*Remote sources* are a mechanism to connect multiple git repositories in a single Garden project. See the [remote sources guide](/features/remote-sources) for more information, including how to use the CLI to manage these sources.

## Plugin commands

Individual plugins (currently referred to as `providers` in your project configuration) may include specific commands that help with their usage and operation. The available commands will depend on which providers are configured in your project.

You can run `garden plugins` without arguments to list the available commands.

### Initializing a Kubernetes cluster for in-cluster building

When using a remote Kubernetes cluster and in-cluster building, the cluster needs to be set up with some shared services when you first start using it, when you update the provider configuration, or sometimes when you update to a new Garden version. See the [remote kubernetes guide](/using-garden-with/kubernetes/remote-kubernetes) for more information.

Here we initialize the cluster configured for the `dev` environment:

```sh
garden plugins kubernetes cluster-init --env=dev
```

### Planning and applying Terraform stacks

The `terraform` provider includes several commands that facilitate interaction with the Terraform stacks in your project. See the [Terraform guide](/using-garden-with/terraform) for more information.

## Plugin tools

Garden plugins generally define their external tool dependencies, such that Garden can automatically fetch them ahead of use. The `garden tools` command exposes these tools, so that you can use them without having to install them separately. You can also use these to ensure that you're using the exact same versions as the Garden plugins.

{% hint style="warning" %}
Note that this command currently only works when run within a Garden project root.
{% endhint %}

If you use this frequently, we recommend defining the following helper function for quick access:

```sh
# Note: This is made to work in bash and zsh, other shells may need a different syntax
function gt() {
  garden tools $1 -- "${@:2}"
}
```

You can then type e.g. `gt docker build .` to run `docker build .` using the Garden-provided version of the `docker CLI`.

Run `garden tools` to get a full list of available tools, and `garden tools --help` for more usage information.

### Running a plugin tool

Note that the `--` is necessary to distinguish between Garden options, and kubectl arguments. See above for a shorthand function you can put in your shell profile.

```sh
garden tools kubectl -- <args>
```

### Getting the path of a plugin tool

This prints the absolute path to the `kubectl` binary defined by the `kubernetes` provider, downloading it first if necessary.

```sh
garden tools kubectl --get-path
```

## Next Steps

Take a look at our [Guides section](https://github.com/garden-io/garden/blob/latest-release/docs/guides/README.md) for in-depth guides on specific use cases and setups, or keep exploring other sections under [Using Garden](https://github.com/garden-io/garden/blob/latest-release/docs/guides/README.md) to learn more about Garden concepts and configuration.


# Using Garden in CircleCI

### Prerequisites

In addition to the prerequisites in the [Portable CI Pipelines that Run Anywhere](/overview/use-cases/portable-ci-pipelines) doc.

For the purposes of this example we'll be using [CircleCI](https://circleci.com) and deploying to a Google Kubernetes Engine (GKE) cluster.

### Project overview

The project is based on our basic [demo-project](https://github.com/garden-io/garden/tree/0.14.20/examples/demo-project) example, but configured for multiple environments. Additionally it contains a CircleCI config file. You'll find the entire source code [here](https://github.com/garden-io/ci-demo-project).

The CI pipeline is configured so that Garden tests the project and deploys it to a **preview** environment on every pull request. Additionally, it tests the project and deploys it to a separate **staging** environment on every merge to the `main` branch.

To see it in action, you can fork the repository and follow the set-up steps below. Once you've set everything up, you can submit a pull request to the fork to trigger a CircleCI job which in turns deploys the project to your remote Kubernetes cluster.

### Configure remote environments

Configuring Garden to work against a remote Kubernetes cluster is explained step by step in our [Remote Kubernetes guide](/using-garden-with/kubernetes).

For this project we're using three environments: `local`, `preview` and `staging`. The `local` environment is the default and is configured for a local Kubernetes cluster that runs on the user's machine. The other two run on remote clusters.

We deploy to the `preview` environment every time someone makes a pull request on Github. The configuration looks like this:

```yaml
# garden.yml
apiVersion: garden.io/v2
kind: Project
name: ci-demo-project
environments:
  ...
  - name: preview
    defaultNamespace: preview-${local.env.CIRCLE_BRANCH || local.username}
providers:
  - name: kubernetes
    environments: [preview]
    context: my-preview-cluster
    defaultHostname: ${environment.namespace}.preview.my-domain
    buildMode: cluster-buildkit
```

Notice that we're using the `CIRCLE_BRANCH` environment variable to label the project namespace. This ensures that each pull request gets deployed into its own namespace.

The `staging` environment is configured in a similar manner. The relevant CI job is triggered on merges to the `main` branch.

You'll find the rest of the config [here](https://github.com/garden-io/ci-demo-project/blob/main/garden.yml).

### Configure the kubectl context

We need to make sure that it can access our remote cluster. We do this by setting up a [kubectl context](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) on the CI agent. How you set this up will vary by how and where you have deployed your cluster. What follows is specific to GKE.

We create a re-usable command for configuring the kubectl context:

```yaml
# .circleci/config
commands:
  configure_kubectl_context:
    description: Configure the kubectl context so that we can access our remote cluster
    steps:
      - run:
          name: Configure kubectl context via gcloud
          command: |
            gcloud --quiet components update
            echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=-
            gcloud --quiet config set project $GCLOUD_PROJECT_ID && gcloud --quiet config set compute/zone $GCLOUD_COMPUTE_ZONE
            gcloud --quiet container clusters get-credentials $GCLOUD_CLUSTER_ID --zone $GCLOUD_COMPUTE_ZONE
            gcloud --quiet auth configure-docker
```

The commands use the following environment variables that you can set on the **Project Environment Variables** page (see [here](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project)) in the CircleCI dashboard:

* `GCLOUD_SERVICE_KEY`: Follow [these instructions](https://cloud.google.com/sdk/docs/authorizing#authorizing_with_a_service_account) to get a service account key.
* `GCLOUD_PROJECT_ID`, `GCLOUD_COMPUTE_ZONE`, and `GCLOUD_CLUSTER_ID`: These you'll find under the relevant project in your Google Cloud Platform console.

Please refer to this [doc](https://circleci.com/docs/2.0/google-auth/) for more information on using the Google Cloud SDK in CircleCI.

You'll find the entire CircleCI config for this project [here](https://github.com/garden-io/ci-demo-project/blob/main/.circleci/config.yml).

### Running Garden commands in CircleCI

Now that we have everything set up, we can [add the project](https://circleci.com/docs/2.0/getting-started/#setting-up-your-build-on-circleci) to CircleCI and start using Garden in our CI pipelines.

Note: Below we use the `gardendev/garden-gcloud` container image, that extends the standard `gardendev/garden` image to bundle the `gcloud` binary (Google Cloud CLI). For an overview of all official Garden convenience containers, please refer to [the reference guide for DockerHub containers](/reference/dockerhub-containers).

Here's what our preview job looks like:

```yaml
# .circleci/config
jobs:
  preview:
    docker:
      - image: gardendev/garden-gcloud:bonsai-alpine
    environment:
      GARDEN_LOG_LEVEL: verbose # set the log level to your preference here
    steps:
      - checkout
      - configure_kubectl_context
      - run:
          name: Test project
          command: garden test --env=preview
      - run:
          name: Deploy project
          command: garden deploy --env=preview
```

Notice that there are no configuration steps outside of just configuring the kubectl context. And no matter how you change your stack, these steps will remain the same, making for a highly portable workflow—and much less fiddling around with CI!


# Minimal RBAC Configuration for Development Clusters

The following describes the minimal RBAC roles and permissions required for day-to-day use by developers for Garden when using the `kubernetes` plugin. These should be created along with the kubeconfig/kubecontext for the user in their namespace, replacing the `<username>`, `<service-accounts-namespace>` and `<project-namespace>` values as appropriate.

```yaml
---
# The user service account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: user-<username>
  namespace: <service-accounts-namespace>

---

# Project namespaces
apiVersion: v1
kind: Namespace
metadata:
  name: <project-namespace>
  # Some required annotations
  annotations:
    garden.io/version: "0.11.3"

---

# Allow reading namespaces and persistent volumes, which are cluster-scoped
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: user-<username>
rules:
- apiGroups: [""]
  resources: ["namespaces", "persistentvolumes"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: user-<username>
  namespace: <service-accounts-namespace>
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: user-<username>
subjects:
- namespace: <service-accounts-namespace>
  kind: ServiceAccount
  name: user-<username>

---

# Full permissions within the <project-namespace>
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: <project-namespace>
  namespace: <project-namespace>
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: <project-namespace>
  namespace: <project-namespace>
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: <project-namespace>
subjects:
- namespace: <service-accounts-namespace>
  kind: ServiceAccount
  name: user-<username>

---

# Required access for the garden-system namespace
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: garden-system
  name: user-<username>-common
rules:
  # Allow storing and reading test results
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "create"]
  # Allow getting status of shared services
- apiGroups: [""]
  resources:
  - "configmaps"
  - "services"
  - "serviceaccounts"
  - "persistentvolumeclaims"
  - "pods/log"
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["configmaps", "services", "serviceaccounts"]
  verbs: ["get", "list"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["roles", "rolebindings"]
  verbs: ["get", "list"]
  # Note: We do not store anything sensitive in secrets, aside from registry auth,
  #       which users anyway need to be able to read and push built images.
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user-<username>-common
  namespace: garden-system
roleRef:
  kind: Role
  name: user-<username>-common
  apiGroup: ""
subjects:
- namespace: <service-accounts-namespace>
  kind: ServiceAccount
  name: user-<username>
```


# Deploying to Production

Depending on your setup and requirements, you may or may not want to use Garden to deploy to your production environment. In either case, if you do configure your production environment in your Garden project configuration, we highly recommend that you set the [production flag](/reference/project-config#environmentsproduction) on it.

This will protect against accidentally messing with your production environments, by prompting for confirmation before e.g. deploying or running tests in the environment.

The flag is also given to each provider, which may modify behavior accordingly. In particular, when used with the `kubernetes` provider, it will do the following:

1. Set the default number of replicas for `container` Deploy actions to 3 (unless specified by the user).
2. Set a soft AntiAffinity setting for `container` Deploy actions to try to schedule Pods in a single Deployment across many nodes.
3. Set a restricted `securityContext` for Pods (runAsUser: 1000, runAsGroup: 3000, fsGroup: 2000) for `container` Deploy actions.
4. Increase the `RevisionHistoryLimit` on workloads to 10.
5. By default, running `garden deploy --force` will propagate the `--force` flag to `helm upgrade`, and set the `--replace` flag on `helm install` when deploying `helm` actions. This may be okay while developing but risky in production, so the `production` flag prevents both of those.

We would highly appreciate feedback on other configuration settings that should be altered when `production: true`. Please send us feedback via [GitHub issues](https://github.com/garden-io/garden/issues) or reach out on [Garden Discussions](https://github.com/garden-io/garden/discussions)!


# Using a Registry Mirror

Garden uses a handful of utility container images that are hosted on [Docker Hub](https://hub.docker.com/) under the `gardendev` repository. These are used for various Kubernetes tasks such as managing syncs and are usually deployed into a given project namespace along with the rest of the project services.

If you have your own Docker Hub registry mirror you can configure Garden to use that instead of Docker Hub. Using your own registry mirror can improve performance because the mirror is typically in your VPC and prevents you from being rate limited by Docker Hub (see also [this FAQ entry](/misc/faq#how-do-i-avoid-being-rate-limited-by-docker-hub) on Docker Hub rate limiting).

To tell Garden to use your custom registry mirror instead of Docker Hub, set the `utilImageRegistryDomain` field on the Kubernetes provider, for example:

```yaml
kind: Project
name: my-project
#...
providers:
  - name: kubernetes
    utilImageRegistryDomain: https://<my-private-registry-domain>
```

This option is available for both the `local-kubernetes` and `kubernetes` providers.

Now when you run a Garden command, the utility images will be pulled from the registry mirror.


# Providers

* [`container`](/reference/providers/container)
* [`exec`](/reference/providers/exec)
* [`jib`](/reference/providers/jib)
* [`kubernetes`](/reference/providers/kubernetes)
* [`local-kubernetes`](/reference/providers/local-kubernetes)
* [`terraform`](/reference/providers/terraform)
* [`pulumi`](/reference/providers/pulumi)


# container

## Description

Provides the `container` actions and module type. *Note that this provider is currently automatically included, and you do not need to configure it in your project configuration.*

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # Extra flags to pass to the `docker build` command. Will extend the `spec.extraFlags` specified in each container
    # Build action.
    dockerBuildExtraFlags:

    gardenContainerBuilder:
      # Enable Remote Container Builder, which can speed up builds significantly using fast machines and extremely
      # fast caching. When the project is connected and you're logged in to https://app.garden.io the container
      # builder will be enabled by default.
      #
      # Under the hood, enabling this option means that Garden will install a remote buildx driver on your local
      # Docker daemon, and use that for builds. See also https://docs.docker.com/build/drivers/remote/
      #
      # In addition to this setting, the environment variable `GARDEN_CONTAINER_BUILDER` can be used to override this
      # setting, if enabled in the configuration. Set it to `false` or `0` to temporarily disable Remote Container
      # Builder.
      #
      # If service limits are reached, or Remote Container Builder is not available, Garden will fall back to building
      # images locally, or it falls back to building in your Kubernetes cluster in case in-cluster building is
      # configured in the Kubernetes provider configuration.
      #
      # Please note that when enabling Container Builder together with in-cluster building, you need to authenticate
      # to your `deploymentRegistry` from the local machine (e.g. by running `docker login`).
      enabled: false
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - name: "local-kubernetes"
```

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].dockerBuildExtraFlags[]`

[providers](#providers) > dockerBuildExtraFlags

Extra flags to pass to the `docker build` command. Will extend the `spec.extraFlags` specified in each container Build action.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `providers[].gardenContainerBuilder`

[providers](#providers) > gardenContainerBuilder

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].gardenContainerBuilder.enabled`

[providers](#providers) > [gardenContainerBuilder](#providersgardencontainerbuilder) > enabled

Enable Remote Container Builder, which can speed up builds significantly using fast machines and extremely fast caching. When the project is connected and you're logged in to <https://app.garden.io> the container builder will be enabled by default.

Under the hood, enabling this option means that Garden will install a remote buildx driver on your local Docker daemon, and use that for builds. See also <https://docs.docker.com/build/drivers/remote/>

In addition to this setting, the environment variable `GARDEN_CONTAINER_BUILDER` can be used to override this setting, if enabled in the configuration. Set it to `false` or `0` to temporarily disable Remote Container Builder.

If service limits are reached, or Remote Container Builder is not available, Garden will fall back to building images locally, or it falls back to building in your Kubernetes cluster in case in-cluster building is configured in the Kubernetes provider configuration.

Please note that when enabling Container Builder together with in-cluster building, you need to authenticate to your `deploymentRegistry` from the local machine (e.g. by running `docker login`).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |


# exec

## Description

A simple provider that allows running arbitrary scripts when initializing providers, and provides the exec action type.

*Note: This provider is always loaded when running Garden. You only need to explicitly declare it in your provider configuration if you want to configure a script for it to run.*

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    #
    # Example: `["exec"]`
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    #
    # Example: `["dev","stage"]`
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # DEPRECATED: Use the `preInit.runScript` field instead on any provider that needs setup outside of Garden.
    #
    # An optional script to run in the project root when initializing providers. This is handy for running an
    # arbitrary
    # script when initializing. For example, another provider might declare a dependency on this provider, to ensure
    # this script runs before resolving that provider.
    initScript:
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

Example: `["exec"]`

| Type    | Default | Required |
| ------- | ------- | -------- |
| `array` | `[]`    | No       |

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

Example: `["dev","stage"]`

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].initScript`

[providers](#providers) > initScript

DEPRECATED: Use the `preInit.runScript` field instead on any provider that needs setup outside of Garden.

An optional script to run in the project root when initializing providers. This is handy for running an arbitrary script when initializing. For example, another provider might declare a dependency on this provider, to ensure this script runs before resolving that provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

## Outputs

The following keys are available via the `${providers.<provider-name>}` template string key for `exec` providers.

### `${providers.<provider-name>.outputs.initScript.log}`

The log output from the initScript specified in the provider configuration, if any.

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |


# jib

## Description

**EXPERIMENTAL**: Please provide feedback via GitHub issues or our community forum!

Provides support for [Jib](https://github.com/GoogleContainerTools/jib) via the [jib action type](/reference/action-types/build/jib-container).

Use this to efficiently build container images for Java services. Check out the [jib example](https://github.com/garden-io/garden/tree/0.14.20/examples/jib-container) to see it in action.

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - name: "local-kubernetes"
```

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |


# kubernetes

## Description

The `kubernetes` provider adds the [`helm`](/using-garden-with/kubernetes/install-helm-chart) and [`kubernetes`](/using-garden-with/kubernetes/deploy-k8s-resource) action types.

For usage information, please refer to the [guides section](https://github.com/garden-io/garden/blob/latest-release/docs/guides/README.md). A good place to start is the [Remote Kubernetes guide](/using-garden-with/kubernetes/remote-kubernetes) guide if you're connecting to remote clusters. The [Quickstart guide](/getting-started/quickstart) guide is also helpful as an introduction.

Note that if you're using a local Kubernetes cluster (e.g. minikube or Docker Desktop), the [local-kubernetes provider](/reference/providers/local-kubernetes) simplifies (and automates) the configuration and setup quite a bit.

Please note that Garden is committed to supporting [the *latest officially supported* versions](https://kubernetes.io/releases/). The information on the Kubernetes support and EOL timelines can be found [here](https://endoflife.date/kubernetes).

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # The container registry domain that should be used for pulling Garden utility images (such as the
    # image used in the Kubernetes sync utility Pod).
    #
    # If you have your own Docker Hub registry mirror, you can set the domain here and the utility images
    # will be pulled from there. This can be useful to e.g. avoid Docker Hub rate limiting.
    #
    # Otherwise the utility images are pulled directly from Docker Hub by default.
    utilImageRegistryDomain: docker.io

    # Choose the mechanism for building container images before deploying. By default your local Docker daemon is
    # used, but you can set it to `cluster-buildkit` or `kaniko` to sync files to the cluster, and build container
    # images there. This removes the need to run Docker locally, and allows you to share layer and image caches
    # between multiple developers, as well as between your development and CI workflows.
    #
    # For more details on all the different options and what makes sense to use for your setup, please check out the
    # [in-cluster building guide](https://docs.garden.io/cedar-0.14/kubernetes-plugins/guides/in-cluster-building).
    buildMode: local-docker

    # Configuration options for the `cluster-buildkit` build mode.
    clusterBuildkit: {}
      # Use the `cache` configuration to customize the default cluster-buildkit cache behaviour.
      #
      # The default value is:
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       mode: auto
      #
      # For every build, this will
      # - import cached layers from a docker image tag named `_buildcache`
      # - when the build is finished, upload cache information to `_buildcache`
      #
      # For registries that support it, `mode: auto` (the default) will enable the buildkit `mode=max`
      # option.
      #
      # See the following table for details on our detection mechanism:
      #
      # | Registry Name                   | Registry Domain                    | Assumed `mode=max` support |
      # |---------------------------------|------------------------------------|------------------------------|
      # | AWS Elastic Container Registry  | `dkr.ecr.<region>.amazonaws.com` | Yes (with `image-manifest=true`) |
      # | Google Cloud Artifact Registry  | `pkg.dev`                        | Yes                          |
      # | Azure Container Registry        | `azurecr.io`                     | Yes                          |
      # | GitHub Container Registry       | `ghcr.io`                        | Yes                          |
      # | DockerHub                       | `index.docker.io`                | Yes                          |
      # | Any other registry              |                                    | No                           |
      #
      # In case you need to override the defaults for your registry, you can do it like so:
      #
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       mode: max
      #
      # When you add multiple caches, we will make sure to pass the `--import-cache` options to buildkit in the same
      # order as provided in the cache configuration. This is because buildkit will not actually use all imported
      # caches
      # for every build, but it will stick with the first cache that yields a cache hit for all the following layers.
      #
      # An example for this is the following:
      #
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       tag: _buildcache-${slice(kebabCase(git.branch), "0", "30")}
      #     - type: registry
      #       tag: _buildcache-main
      #       export: false
      #
      # Using this cache configuration, every build will first look for a cache specific to your feature branch.
      # If it does not exist yet, it will import caches from the main branch builds (`_buildcache-main`).
      # When the build is finished, it will only export caches to your feature branch, and avoid polluting the `main`
      # branch caches.
      # A configuration like that may improve your cache hit rate and thus save time.
      #
      # If you need to disable caches completely you can achieve that with the following configuration:
      #
      # clusterBuildkit:
      #   cache: []
      cache:
        - # Use the Docker registry configured at `deploymentRegistry` to retrieve and store buildkit cache
          # information.
          #
          # See also the [buildkit registry cache
          # documentation](https://github.com/moby/buildkit#registry-push-image-and-cache-separately)
          type:

          # The registry from which the cache should be imported from, or which it should be exported to.
          #
          # If not specified, use the configured `deploymentRegistry` in your kubernetes provider config.
          #
          # Important: You must make sure `imagePullSecrets` includes authentication with the specified cache
          # registry, that has the appropriate write privileges (usually full write access to the configured
          # `namespace`).
          registry:
            # The hostname (and optionally port, if not the default port) of the registry.
            hostname:

            # The port where the registry listens on, if not the default.
            port:

            # The registry namespace. Will be placed between hostname and image name, like so:
            # <hostname>/<namespace>/<image name>
            namespace:

            # Set to true to allow insecure connections to the registry (without SSL).
            insecure: false

          # This is the buildkit cache mode to be used.
          #
          # The value `inline` ensures that garden is using the buildkit option `--export-cache inline`. Cache
          # information will be inlined and co-located with the Docker image itself.
          #
          # The values `min` and `max` ensure that garden passes the `mode=max` or `mode=min` modifiers to the
          # buildkit `--export-cache` option. Cache manifests will only be
          # stored stored in the configured `tag`.
          #
          # `auto` is the same as `max` for some registries that are known to support it. Garden will fall back to
          # `inline` for all other registries.
          #  See the [clusterBuildkit cache option](#providersclusterbuildkitcache) for a description of the detection
          # mechanism.
          #
          # See also the [buildkit export cache documentation](https://github.com/moby/buildkit#export-cache)
          mode: auto

          # This is the Docker registry tag name buildkit should use for the registry build cache. Default is
          # `_buildcache`
          #
          # **NOTE**: `tag` can only be used together with the `registry` cache type
          tag: _buildcache

          # If this is false, only pass the `--import-cache` option to buildkit, and not the `--export-cache` option.
          # Defaults to true.
          export: true

      # Enable rootless mode for the cluster-buildkit daemon, which runs the daemon with decreased privileges.
      # Please see [the buildkit docs](https://github.com/moby/buildkit/blob/master/docs/rootless.md) for caveats when
      # using this mode.
      rootless: false

      # Exposes the `nodeSelector` field on the PodSpec of the BuildKit deployment. This allows you to constrain the
      # BuildKit daemon to only run on particular nodes.
      #
      # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes
      # guide to assigning Pods to nodes.
      nodeSelector: {}

      # Specify tolerations to apply to cluster-buildkit daemon. Useful to control which nodes in a cluster can run
      # builds.
      tolerations:
        - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
          # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
          effect:

          # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
          # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
          key:

          # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
          # Defaults to
          # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
          # particular category.
          operator: Equal

          # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
          # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
          # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
          # by the system.
          tolerationSeconds:

          # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
          # empty,
          # otherwise just a regular string.
          value:

      # Specify annotations to apply to both the Pod and Deployment resources associated with cluster-buildkit.
      # Annotations may have an effect on the behaviour of certain components, for example autoscalers.
      annotations:

      # Specify annotations to apply to the Kubernetes service account used by cluster-buildkit. This can be useful to
      # set up IRSA with in-cluster building.
      serviceAccountAnnotations:

    # Setting related to Jib image builds.
    jib:
      # In some cases you may need to push images built with Jib to the remote registry via Kubernetes cluster, e.g.
      # if you don't have connectivity or access from where Garden is being run. In that case, set this flag to true,
      # but do note that the build will take considerably take longer to complete! Only applies when using in-cluster
      # building.
      pushViaCluster: false

    # Configuration options for the `kaniko` build mode.
    kaniko:
      # Specify extra flags to use when building the container image with kaniko. Flags set on `container` Builds take
      # precedence over these.
      extraFlags:

      # Change the kaniko image (repository/image:tag) to use when building in kaniko mode.
      image: >-
  gcr.io/kaniko-project/executor:v1.11.0-debug@sha256:32ba2214921892c2fa7b5f9c4ae6f8f026538ce6b2105a93a36a8b5ee50fe517

      # Choose the namespace where the Kaniko pods will be run. Defaults to the project namespace.
      namespace:

      # Exposes the `nodeSelector` field on the PodSpec of the Kaniko pods. This allows you to constrain the Kaniko
      # pods to only run on particular nodes. The same nodeSelector will be used for each util pod unless they are
      # specifically set under `util.nodeSelector`.
      #
      # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes
      # guide to assigning pods to nodes.
      nodeSelector:

      # Specify tolerations to apply to each Kaniko builder pod. Useful to control which nodes in a cluster can run
      # builds. The same tolerations will be used for each util pod unless they are specifically set under
      # `util.tolerations`
      tolerations:
        - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
          # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
          effect:

          # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
          # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
          key:

          # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
          # Defaults to
          # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
          # particular category.
          operator: Equal

          # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
          # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
          # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
          # by the system.
          tolerationSeconds:

          # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
          # empty,
          # otherwise just a regular string.
          value:

      # Specify annotations to apply to each Kaniko builder pod. Annotations may have an effect on the behaviour of
      # certain components, for example autoscalers. The same annotations will be used for each util pod unless they
      # are specifically set under `util.annotations`
      annotations:

      # Specify annotations to apply to the Kubernetes service account used by kaniko. This can be useful to set up
      # IRSA with in-cluster building.
      serviceAccountAnnotations:

      util:
        # Specify tolerations to apply to each garden-util pod.
        tolerations:
          - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
            # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
            effect:

            # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
            # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
            key:

            # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
            # Defaults to
            # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
            # particular category.
            operator: Equal

            # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
            # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
            # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
            # by the system.
            tolerationSeconds:

            # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
            # empty,
            # otherwise just a regular string.
            value:

        # Specify annotations to apply to each garden-util pod and deployments.
        annotations:

        # Specify the nodeSelector constraints for each garden-util pod.
        nodeSelector:

    # A default hostname to use when no hostname is explicitly configured for a service.
    defaultHostname:

    # Configuration options for code synchronization.
    sync:
      # Specifies default settings for syncs (e.g. for `container`, `kubernetes` and `helm` services).
      #
      # These are overridden/extended by the settings of any individual sync specs.
      #
      # Sync is enabled e.g by setting the `--sync` flag on the `garden deploy` command.
      #
      # See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for more
      # information.
      defaults:
        # Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.
        #
        # Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.
        #
        # `.git` directories and `.garden` directories are always ignored.
        exclude:

        # The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644
        # (user can read/write, everyone else can read). See the [Mutagen
        # docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.
        fileMode: 420

        # The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to
        # 0o755 (user can read/write, everyone else can read). See the [Mutagen
        # docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.
        directoryMode: 493

        # Set the default owner of files and directories at the target. Specify either an integer ID or a string name.
        # See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for
        # more information.
        owner:

        # Set the default group on files and directories at the target. Specify either an integer ID or a string name.
        # See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for
        # more information.
        group:

    # Require SSL on all `container` Deploys. If set to true, an error is raised when no certificate is available for
    # a configured hostname on a `container`Deploy.
    forceSsl: false

    # References to `docker-registry` secrets to use for authenticating with remote registries when pulling
    # images. This is necessary if you reference private images in your action configuration, and is required
    # when configuring a remote Kubernetes environment with buildMode=local.
    imagePullSecrets:
      - # The name of the Kubernetes secret.
        name:

        # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
        # namespace before use.
        namespace: default

    # References to secrets you need to have copied into all namespaces deployed to. These secrets will be
    # ensured to exist in the namespace before deploying any service.
    copySecrets:
      - # The name of the Kubernetes secret.
        name:

        # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
        # namespace before use.
        namespace: default

    # Resource requests and limits for the in-cluster builder..
    resources:
      # Resource requests and limits for the in-cluster builder. It's important to consider which build mode you're
      # using when configuring this.
      #
      # When `buildMode` is `kaniko`, this refers to _each Kaniko pod_, i.e. each individual build, so you'll want to
      # consider the requirements for your individual image builds, with your most expensive/heavy images in mind.
      #
      # When `buildMode` is `cluster-buildkit`, this applies to the BuildKit deployment created in _each project
      # namespace_. So think of this as the resource spec for each individual user or project namespace.
      builder:
        limits:
          # CPU limit in millicpu.
          cpu: 4000

          # Memory limit in megabytes.
          memory: 8192

          # Ephemeral storage limit in megabytes.
          ephemeralStorage:

        requests:
          # CPU request in millicpu.
          cpu: 100

          # Memory request in megabytes.
          memory: 512

          # Ephemeral storage request in megabytes.
          ephemeralStorage:

      # Resource requests and limits for the util pod for in-cluster builders.
      # This pod is used to get, start, stop and inquire the status of the builds.
      #
      # This pod is created in each garden namespace.
      util:
        limits:
          # CPU limit in millicpu.
          cpu: 256

          # Memory limit in megabytes.
          memory: 512

          # Ephemeral storage limit in megabytes.
          ephemeralStorage:

        requests:
          # CPU request in millicpu.
          cpu: 256

          # Memory request in megabytes.
          memory: 512

          # Ephemeral storage request in megabytes.
          ephemeralStorage:

    # One or more certificates to use for ingress.
    tlsCertificates:
      - # A unique identifier for this certificate.
        name:

        # A list of hostnames that this certificate should be used for. If you don't specify these, they will be
        # automatically read from the certificate.
        hostnames:

        # A reference to the Kubernetes secret that contains the TLS certificate and key for the domain.
        secretRef:
          # The name of the Kubernetes secret.
          name:

          # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
          # namespace before use.
          namespace: default

    # Exposes the `nodeSelector` field on the PodSpec of system services. This allows you to constrain the system
    # services to only run on particular nodes.
    #
    # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide
    # to assigning Pods to nodes.
    systemNodeSelector: {}

    # The name of the provider plugin to use.
    name: kubernetes

    # The kubectl context to use to connect to the Kubernetes cluster.
    context:

    # The registry where built containers should be pushed to, and then pulled to the cluster when deploying services.
    #
    # Important: If you specify this in combination with in-cluster building, you must make sure `imagePullSecrets`
    # includes authentication with the specified deployment registry, that has the appropriate write privileges
    # (usually full write access to the configured `deploymentRegistry.namespace`).
    deploymentRegistry:
      # The hostname (and optionally port, if not the default port) of the registry.
      hostname:

      # The port where the registry listens on, if not the default.
      port:

      # The registry namespace. Will be placed between hostname and image name, like so: <hostname>/<namespace>/<image
      # name>
      namespace:

      # Set to true to allow insecure connections to the registry (without SSL).
      insecure: false

    # The ingress class or ingressClassName to use on configured Ingresses (via the `kubernetes.io/ingress.class`
    # annotation or `spec.ingressClassName` field depending on the kubernetes version)
    # when deploying `container` services. Use this if you have multiple ingress controllers in your cluster.
    ingressClass:

    # The external HTTP port of the cluster's ingress controller.
    ingressHttpPort: 80

    # The external HTTPS port of the cluster's ingress controller.
    ingressHttpsPort: 443

    # Path to kubeconfig file to use instead of the system default.
    kubeconfig:

    # Set a specific path to a kubectl binary, instead of having Garden download it automatically as required.
    #
    # It may be useful in some scenarios to allow individual users to set this, e.g. with an environment variable. You
    # could configure that with something like `kubectlPath: ${local.env.GARDEN_KUBECTL_PATH}?`.
    #
    # **Warning**: Garden may make some assumptions with respect to the kubectl version, so it is suggested to only
    # use this when necessary.
    kubectlPath:

    # Specify which namespace to deploy services to, and optionally annotations/labels to apply to the namespace.
    #
    # You can specify a string as a shorthand for `name: <name>`. Defaults to `<project name>-<environment
    # namespace>`.
    #
    # Note that the framework may generate other namespaces as well with this name as a prefix. Also note that if the
    # namespace previously exists, Garden will attempt to add the specified labels and annotations. If the user does
    # not have permissions to do so, a warning is shown.
    namespace:
      # A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters,
      # numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63
      # characters.
      name:

      # Map of annotations to apply to the namespace when creating it.
      annotations:

      # Map of labels to apply to the namespace when creating it.
      labels:

    # Set this to `traefik` or `nginx` to install the respective ingress controller. The nginx controller is
    # deprecated and will be removed in a future version — we recommend using `traefik`.
    setupIngressController: false
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].utilImageRegistryDomain`

[providers](#providers) > utilImageRegistryDomain

The container registry domain that should be used for pulling Garden utility images (such as the image used in the Kubernetes sync utility Pod).

If you have your own Docker Hub registry mirror, you can set the domain here and the utility images will be pulled from there. This can be useful to e.g. avoid Docker Hub rate limiting.

Otherwise the utility images are pulled directly from Docker Hub by default.

| Type     | Default       | Required |
| -------- | ------------- | -------- |
| `string` | `"docker.io"` | No       |

### `providers[].buildMode`

[providers](#providers) > buildMode

Choose the mechanism for building container images before deploying. By default your local Docker daemon is used, but you can set it to `cluster-buildkit` or `kaniko` to sync files to the cluster, and build container images there. This removes the need to run Docker locally, and allows you to share layer and image caches between multiple developers, as well as between your development and CI workflows.

For more details on all the different options and what makes sense to use for your setup, please check out the [in-cluster building guide](https://docs.garden.io/cedar-0.14/kubernetes-plugins/guides/in-cluster-building).

| Type     | Allowed Values                               | Default          | Required |
| -------- | -------------------------------------------- | ---------------- | -------- |
| `string` | "local-docker", "kaniko", "cluster-buildkit" | `"local-docker"` | Yes      |

### `providers[].clusterBuildkit`

[providers](#providers) > clusterBuildkit

Configuration options for the `cluster-buildkit` build mode.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `providers[].clusterBuildkit.cache[]`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > cache

Use the `cache` configuration to customize the default cluster-buildkit cache behaviour.

The default value is:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      mode: auto
```

For every build, this will

* import cached layers from a docker image tag named `_buildcache`
* when the build is finished, upload cache information to `_buildcache`

For registries that support it, `mode: auto` (the default) will enable the buildkit `mode=max` option.

See the following table for details on our detection mechanism:

| Registry Name                  | Registry Domain                  | Assumed `mode=max` support       |
| ------------------------------ | -------------------------------- | -------------------------------- |
| AWS Elastic Container Registry | `dkr.ecr.<region>.amazonaws.com` | Yes (with `image-manifest=true`) |
| Google Cloud Artifact Registry | `pkg.dev`                        | Yes                              |
| Azure Container Registry       | `azurecr.io`                     | Yes                              |
| GitHub Container Registry      | `ghcr.io`                        | Yes                              |
| DockerHub                      | `index.docker.io`                | Yes                              |
| Any other registry             |                                  | No                               |

In case you need to override the defaults for your registry, you can do it like so:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      mode: max
```

When you add multiple caches, we will make sure to pass the `--import-cache` options to buildkit in the same order as provided in the cache configuration. This is because buildkit will not actually use all imported caches for every build, but it will stick with the first cache that yields a cache hit for all the following layers.

An example for this is the following:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      tag: _buildcache-${slice(kebabCase(git.branch), "0", "30")}
    - type: registry
      tag: _buildcache-main
      export: false
```

Using this cache configuration, every build will first look for a cache specific to your feature branch. If it does not exist yet, it will import caches from the main branch builds (`_buildcache-main`). When the build is finished, it will only export caches to your feature branch, and avoid polluting the `main` branch caches. A configuration like that may improve your cache hit rate and thus save time.

If you need to disable caches completely you can achieve that with the following configuration:

```yaml
clusterBuildkit:
  cache: []
```

| Type            | Default                                                                 | Required |
| --------------- | ----------------------------------------------------------------------- | -------- |
| `array[object]` | `[{"type":"registry","mode":"auto","tag":"_buildcache","export":true}]` | No       |

### `providers[].clusterBuildkit.cache[].type`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > type

Use the Docker registry configured at `deploymentRegistry` to retrieve and store buildkit cache information.

See also the [buildkit registry cache documentation](https://github.com/moby/buildkit#registry-push-image-and-cache-separately)

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "registry"     | Yes      |

### `providers[].clusterBuildkit.cache[].registry`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > registry

The registry from which the cache should be imported from, or which it should be exported to.

If not specified, use the configured `deploymentRegistry` in your kubernetes provider config.

Important: You must make sure `imagePullSecrets` includes authentication with the specified cache registry, that has the appropriate write privileges (usually full write access to the configured `namespace`).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].clusterBuildkit.cache[].registry.hostname`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > hostname

The hostname (and optionally port, if not the default port) of the registry.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      cache:
        - registry:
            ...
            hostname: "gcr.io"
```

### `providers[].clusterBuildkit.cache[].registry.port`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > port

The port where the registry listens on, if not the default.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `providers[].clusterBuildkit.cache[].registry.namespace`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > namespace

The registry namespace. Will be placed between hostname and image name, like so: //

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      cache:
        - registry:
            ...
            namespace: "my-project"
```

### `providers[].clusterBuildkit.cache[].registry.insecure`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > insecure

Set to true to allow insecure connections to the registry (without SSL).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].clusterBuildkit.cache[].mode`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > mode

This is the buildkit cache mode to be used.

The value `inline` ensures that garden is using the buildkit option `--export-cache inline`. Cache information will be inlined and co-located with the Docker image itself.

The values `min` and `max` ensure that garden passes the `mode=max` or `mode=min` modifiers to the buildkit `--export-cache` option. Cache manifests will only be stored stored in the configured `tag`.

`auto` is the same as `max` for some registries that are known to support it. Garden will fall back to `inline` for all other registries. See the [clusterBuildkit cache option](#providersclusterbuildkitcache) for a description of the detection mechanism.

See also the [buildkit export cache documentation](https://github.com/moby/buildkit#export-cache)

| Type     | Allowed Values                 | Default  | Required |
| -------- | ------------------------------ | -------- | -------- |
| `string` | "auto", "min", "max", "inline" | `"auto"` | Yes      |

### `providers[].clusterBuildkit.cache[].tag`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > tag

This is the Docker registry tag name buildkit should use for the registry build cache. Default is `_buildcache`

**NOTE**: `tag` can only be used together with the `registry` cache type

| Type     | Default         | Required |
| -------- | --------------- | -------- |
| `string` | `"_buildcache"` | No       |

### `providers[].clusterBuildkit.cache[].export`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > export

If this is false, only pass the `--import-cache` option to buildkit, and not the `--export-cache` option. Defaults to true.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `providers[].clusterBuildkit.rootless`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > rootless

Enable rootless mode for the cluster-buildkit daemon, which runs the daemon with decreased privileges. Please see [the buildkit docs](https://github.com/moby/buildkit/blob/master/docs/rootless.md) for caveats when using this mode.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].clusterBuildkit.nodeSelector`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > nodeSelector

Exposes the `nodeSelector` field on the PodSpec of the BuildKit deployment. This allows you to constrain the BuildKit daemon to only run on particular nodes.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning Pods to nodes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      nodeSelector:
          disktype: ssd
```

### `providers[].clusterBuildkit.tolerations[]`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > tolerations

Specify tolerations to apply to cluster-buildkit daemon. Useful to control which nodes in a cluster can run builds.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].clusterBuildkit.tolerations[].effect`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].key`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].operator`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].clusterBuildkit.tolerations[].tolerationSeconds`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].value`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.annotations`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > annotations

Specify annotations to apply to both the Pod and Deployment resources associated with cluster-buildkit. Annotations may have an effect on the behaviour of certain components, for example autoscalers.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].clusterBuildkit.serviceAccountAnnotations`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > serviceAccountAnnotations

Specify annotations to apply to the Kubernetes service account used by cluster-buildkit. This can be useful to set up IRSA with in-cluster building.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      serviceAccountAnnotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
```

### `providers[].jib`

[providers](#providers) > jib

Setting related to Jib image builds.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].jib.pushViaCluster`

[providers](#providers) > [jib](#providersjib) > pushViaCluster

In some cases you may need to push images built with Jib to the remote registry via Kubernetes cluster, e.g. if you don't have connectivity or access from where Garden is being run. In that case, set this flag to true, but do note that the build will take considerably take longer to complete! Only applies when using in-cluster building.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].kaniko`

[providers](#providers) > kaniko

Configuration options for the `kaniko` build mode.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.extraFlags[]`

[providers](#providers) > [kaniko](#providerskaniko) > extraFlags

Specify extra flags to use when building the container image with kaniko. Flags set on `container` Builds take precedence over these.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `providers[].kaniko.image`

[providers](#providers) > [kaniko](#providerskaniko) > image

Change the kaniko image (repository/image:tag) to use when building in kaniko mode.

| Type     | Default                                                                                                                  | Required |
| -------- | ------------------------------------------------------------------------------------------------------------------------ | -------- |
| `string` | `"gcr.io/kaniko-project/executor:v1.11.0-debug@sha256:32ba2214921892c2fa7b5f9c4ae6f8f026538ce6b2105a93a36a8b5ee50fe517"` | No       |

### `providers[].kaniko.namespace`

[providers](#providers) > [kaniko](#providerskaniko) > namespace

Choose the namespace where the Kaniko pods will be run. Defaults to the project namespace.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.nodeSelector`

[providers](#providers) > [kaniko](#providerskaniko) > nodeSelector

Exposes the `nodeSelector` field on the PodSpec of the Kaniko pods. This allows you to constrain the Kaniko pods to only run on particular nodes. The same nodeSelector will be used for each util pod unless they are specifically set under `util.nodeSelector`.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning pods to nodes.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.tolerations[]`

[providers](#providers) > [kaniko](#providerskaniko) > tolerations

Specify tolerations to apply to each Kaniko builder pod. Useful to control which nodes in a cluster can run builds. The same tolerations will be used for each util pod unless they are specifically set under `util.tolerations`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].kaniko.tolerations[].effect`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].key`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].operator`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].kaniko.tolerations[].tolerationSeconds`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].value`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.annotations`

[providers](#providers) > [kaniko](#providerskaniko) > annotations

Specify annotations to apply to each Kaniko builder pod. Annotations may have an effect on the behaviour of certain components, for example autoscalers. The same annotations will be used for each util pod unless they are specifically set under `util.annotations`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].kaniko.serviceAccountAnnotations`

[providers](#providers) > [kaniko](#providerskaniko) > serviceAccountAnnotations

Specify annotations to apply to the Kubernetes service account used by kaniko. This can be useful to set up IRSA with in-cluster building.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      serviceAccountAnnotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
```

### `providers[].kaniko.util`

[providers](#providers) > [kaniko](#providerskaniko) > util

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.util.tolerations[]`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > tolerations

Specify tolerations to apply to each garden-util pod.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].kaniko.util.tolerations[].effect`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].key`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].operator`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].kaniko.util.tolerations[].tolerationSeconds`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].value`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.annotations`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > annotations

Specify annotations to apply to each garden-util pod and deployments.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      util:
        ...
        annotations:
            cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].kaniko.util.nodeSelector`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > nodeSelector

Specify the nodeSelector constraints for each garden-util pod.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].defaultHostname`

[providers](#providers) > defaultHostname

A default hostname to use when no hostname is explicitly configured for a service.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - defaultHostname: "api.mydomain.com"
```

### `providers[].sync`

[providers](#providers) > sync

Configuration options for code synchronization.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].sync.defaults`

[providers](#providers) > [sync](#providerssync) > defaults

Specifies default settings for syncs (e.g. for `container`, `kubernetes` and `helm` services).

These are overridden/extended by the settings of any individual sync specs.

Sync is enabled e.g by setting the `--sync` flag on the `garden deploy` command.

See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for more information.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].sync.defaults.exclude[]`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
providers:
  - sync:
      ...
      defaults:
        ...
        exclude:
          - dist/**/*
          - '*.log'
```

### `providers[].sync.defaults.fileMode`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > fileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `providers[].sync.defaults.directoryMode`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > directoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `providers[].sync.defaults.owner`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > owner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `providers[].sync.defaults.group`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > group

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `providers[].forceSsl`

[providers](#providers) > forceSsl

Require SSL on all `container` Deploys. If set to true, an error is raised when no certificate is available for a configured hostname on a `container`Deploy.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].imagePullSecrets[]`

[providers](#providers) > imagePullSecrets

References to `docker-registry` secrets to use for authenticating with remote registries when pulling images. This is necessary if you reference private images in your action configuration, and is required when configuring a remote Kubernetes environment with buildMode=local.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].imagePullSecrets[].name`

[providers](#providers) > [imagePullSecrets](#providersimagepullsecrets) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - imagePullSecrets:
      - name: "my-secret"
```

### `providers[].imagePullSecrets[].namespace`

[providers](#providers) > [imagePullSecrets](#providersimagepullsecrets) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].copySecrets[]`

[providers](#providers) > copySecrets

References to secrets you need to have copied into all namespaces deployed to. These secrets will be ensured to exist in the namespace before deploying any service.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].copySecrets[].name`

[providers](#providers) > [copySecrets](#providerscopysecrets) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - copySecrets:
      - name: "my-secret"
```

### `providers[].copySecrets[].namespace`

[providers](#providers) > [copySecrets](#providerscopysecrets) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].resources`

[providers](#providers) > resources

Resource requests and limits for the in-cluster builder..

| Type     | Default                                                                                                                                                                | Required |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `object` | `{"builder":{"limits":{"cpu":4000,"memory":8192},"requests":{"cpu":100,"memory":512}},"util":{"limits":{"cpu":256,"memory":512},"requests":{"cpu":256,"memory":512}}}` | No       |

### `providers[].resources.builder`

[providers](#providers) > [resources](#providersresources) > builder

Resource requests and limits for the in-cluster builder. It's important to consider which build mode you're using when configuring this.

When `buildMode` is `kaniko`, this refers to *each Kaniko pod*, i.e. each individual build, so you'll want to consider the requirements for your individual image builds, with your most expensive/heavy images in mind.

When `buildMode` is `cluster-buildkit`, this applies to the BuildKit deployment created in *each project namespace*. So think of this as the resource spec for each individual user or project namespace.

| Type     | Default                                                                     | Required |
| -------- | --------------------------------------------------------------------------- | -------- |
| `object` | `{"limits":{"cpu":4000,"memory":8192},"requests":{"cpu":100,"memory":512}}` | No       |

### `providers[].resources.builder.limits`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > limits

| Type     | Default                      | Required |
| -------- | ---------------------------- | -------- |
| `object` | `{"cpu":4000,"memory":8192}` | No       |

### `providers[].resources.builder.limits.cpu`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > cpu

CPU limit in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `4000`  | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          cpu: 4000
```

### `providers[].resources.builder.limits.memory`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > memory

Memory limit in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `8192`  | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          memory: 8192
```

### `providers[].resources.builder.limits.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > ephemeralStorage

Ephemeral storage limit in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.builder.requests`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > requests

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":100,"memory":512}` | No       |

### `providers[].resources.builder.requests.cpu`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > cpu

CPU request in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `100`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          cpu: 100
```

### `providers[].resources.builder.requests.memory`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > memory

Memory request in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          memory: 512
```

### `providers[].resources.builder.requests.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > ephemeralStorage

Ephemeral storage request in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.util`

[providers](#providers) > [resources](#providersresources) > util

Resource requests and limits for the util pod for in-cluster builders. This pod is used to get, start, stop and inquire the status of the builds.

This pod is created in each garden namespace.

| Type     | Default                                                                   | Required |
| -------- | ------------------------------------------------------------------------- | -------- |
| `object` | `{"limits":{"cpu":256,"memory":512},"requests":{"cpu":256,"memory":512}}` | No       |

### `providers[].resources.util.limits`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > limits

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":256,"memory":512}` | No       |

### `providers[].resources.util.limits.cpu`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > cpu

CPU limit in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `256`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          cpu: 256
```

### `providers[].resources.util.limits.memory`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > memory

Memory limit in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          memory: 512
```

### `providers[].resources.util.limits.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > ephemeralStorage

Ephemeral storage limit in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.util.requests`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > requests

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":256,"memory":512}` | No       |

### `providers[].resources.util.requests.cpu`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > cpu

CPU request in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `256`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          cpu: 256
```

### `providers[].resources.util.requests.memory`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > memory

Memory request in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          memory: 512
```

### `providers[].resources.util.requests.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > ephemeralStorage

Ephemeral storage request in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          ephemeralStorage: 8192
```

### `providers[].tlsCertificates[]`

[providers](#providers) > tlsCertificates

One or more certificates to use for ingress.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].tlsCertificates[].name`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > name

A unique identifier for this certificate.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - name: "www"
```

### `providers[].tlsCertificates[].hostnames[]`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > hostnames

A list of hostnames that this certificate should be used for. If you don't specify these, they will be automatically read from the certificate.

| Type              | Required |
| ----------------- | -------- |
| `array[hostname]` | No       |

Example:

```yaml
providers:
  - tlsCertificates:
      - hostnames:
          - www.mydomain.com
```

### `providers[].tlsCertificates[].secretRef`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > secretRef

A reference to the Kubernetes secret that contains the TLS certificate and key for the domain.

| Type     | Required |
| -------- | -------- |
| `object` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - secretRef:
            name: my-tls-secret
            namespace: default
```

### `providers[].tlsCertificates[].secretRef.name`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > [secretRef](#providerstlscertificatessecretref) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - secretRef:
            name: my-tls-secret
            namespace: default
          ...
          name: "my-secret"
```

### `providers[].tlsCertificates[].secretRef.namespace`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > [secretRef](#providerstlscertificatessecretref) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].systemNodeSelector`

[providers](#providers) > systemNodeSelector

Exposes the `nodeSelector` field on the PodSpec of system services. This allows you to constrain the system services to only run on particular nodes.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning Pods to nodes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
providers:
  - systemNodeSelector:
        disktype: ssd
```

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Default        | Required |
| -------- | -------------- | -------- |
| `string` | `"kubernetes"` | Yes      |

Example:

```yaml
providers:
  - name: "kubernetes"
```

### `providers[].context`

[providers](#providers) > context

The kubectl context to use to connect to the Kubernetes cluster.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - context: "my-dev-context"
```

### `providers[].deploymentRegistry`

[providers](#providers) > deploymentRegistry

The registry where built containers should be pushed to, and then pulled to the cluster when deploying services.

Important: If you specify this in combination with in-cluster building, you must make sure `imagePullSecrets` includes authentication with the specified deployment registry, that has the appropriate write privileges (usually full write access to the configured `deploymentRegistry.namespace`).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].deploymentRegistry.hostname`

[providers](#providers) > [deploymentRegistry](#providersdeploymentregistry) > hostname

The hostname (and optionally port, if not the default port) of the registry.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - deploymentRegistry:
      ...
      hostname: "gcr.io"
```

### `providers[].deploymentRegistry.port`

[providers](#providers) > [deploymentRegistry](#providersdeploymentregistry) > port

The port where the registry listens on, if not the default.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `providers[].deploymentRegistry.namespace`

[providers](#providers) > [deploymentRegistry](#providersdeploymentregistry) > namespace

The registry namespace. Will be placed between hostname and image name, like so: //

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - deploymentRegistry:
      ...
      namespace: "my-project"
```

### `providers[].deploymentRegistry.insecure`

[providers](#providers) > [deploymentRegistry](#providersdeploymentregistry) > insecure

Set to true to allow insecure connections to the registry (without SSL).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].ingressClass`

[providers](#providers) > ingressClass

The ingress class or ingressClassName to use on configured Ingresses (via the `kubernetes.io/ingress.class` annotation or `spec.ingressClassName` field depending on the kubernetes version) when deploying `container` services. Use this if you have multiple ingress controllers in your cluster.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].ingressHttpPort`

[providers](#providers) > ingressHttpPort

The external HTTP port of the cluster's ingress controller.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `80`    | No       |

### `providers[].ingressHttpsPort`

[providers](#providers) > ingressHttpsPort

The external HTTPS port of the cluster's ingress controller.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `443`   | No       |

### `providers[].kubeconfig`

[providers](#providers) > kubeconfig

Path to kubeconfig file to use instead of the system default.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kubectlPath`

[providers](#providers) > kubectlPath

Set a specific path to a kubectl binary, instead of having Garden download it automatically as required.

It may be useful in some scenarios to allow individual users to set this, e.g. with an environment variable. You could configure that with something like `kubectlPath: ${local.env.GARDEN_KUBECTL_PATH}?`.

**Warning**: Garden may make some assumptions with respect to the kubectl version, so it is suggested to only use this when necessary.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].namespace`

[providers](#providers) > namespace

Specify which namespace to deploy services to, and optionally annotations/labels to apply to the namespace.

You can specify a string as a shorthand for `name: <name>`. Defaults to `<project name>-<environment namespace>`.

Note that the framework may generate other namespaces as well with this name as a prefix. Also note that if the namespace previously exists, Garden will attempt to add the specified labels and annotations. If the user does not have permissions to do so, a warning is shown.

| Type               | Required |
| ------------------ | -------- |
| `object \| string` | No       |

### `providers[].namespace.name`

[providers](#providers) > [namespace](#providersnamespace) > name

A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63 characters.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].namespace.annotations`

[providers](#providers) > [namespace](#providersnamespace) > annotations

Map of annotations to apply to the namespace when creating it.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - namespace: ''
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].namespace.labels`

[providers](#providers) > [namespace](#providersnamespace) > labels

Map of labels to apply to the namespace when creating it.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].setupIngressController`

[providers](#providers) > setupIngressController

Set this to `traefik` or `nginx` to install the respective ingress controller. The nginx controller is deprecated and will be removed in a future version — we recommend using `traefik`.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `false` | No       |

## Outputs

The following keys are available via the `${providers.<provider-name>}` template string key for `kubernetes` providers.

### `${providers.<provider-name>.outputs.app-namespace}`

The primary namespace used for resource deployments.

| Type     |
| -------- |
| `string` |

### `${providers.<provider-name>.outputs.default-hostname}`

The default hostname configured on the provider.

| Type     |
| -------- |
| `string` |


# local-kubernetes

## Description

The `local-kubernetes` provider is a specialized version of the [`kubernetes` provider](/reference/providers/kubernetes) that automates and simplifies working with local Kubernetes clusters.

For general Kubernetes usage information, please refer to the [Kubernetes guides](https://docs.garden.io/cedar-0.14/kubernetes-plugins/about). For local clusters a good place to start is the [Local Kubernetes](https://docs.garden.io/cedar-0.14/kubernetes-plugins/local-k8s) guide.

If you're working with a remote Kubernetes cluster, please refer to the [`kubernetes` provider](/reference/providers/kubernetes) docs, and the [Remote Kubernetes guide](https://docs.garden.io/cedar-0.14/kubernetes-plugins/remote-k8s) guide.

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # The container registry domain that should be used for pulling Garden utility images (such as the
    # image used in the Kubernetes sync utility Pod).
    #
    # If you have your own Docker Hub registry mirror, you can set the domain here and the utility images
    # will be pulled from there. This can be useful to e.g. avoid Docker Hub rate limiting.
    #
    # Otherwise the utility images are pulled directly from Docker Hub by default.
    utilImageRegistryDomain: docker.io

    # Choose the mechanism for building container images before deploying. By default your local Docker daemon is
    # used, but you can set it to `cluster-buildkit` or `kaniko` to sync files to the cluster, and build container
    # images there. This removes the need to run Docker locally, and allows you to share layer and image caches
    # between multiple developers, as well as between your development and CI workflows.
    #
    # For more details on all the different options and what makes sense to use for your setup, please check out the
    # [in-cluster building guide](https://docs.garden.io/cedar-0.14/kubernetes-plugins/guides/in-cluster-building).
    buildMode: local-docker

    # Configuration options for the `cluster-buildkit` build mode.
    clusterBuildkit: {}
      # Use the `cache` configuration to customize the default cluster-buildkit cache behaviour.
      #
      # The default value is:
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       mode: auto
      #
      # For every build, this will
      # - import cached layers from a docker image tag named `_buildcache`
      # - when the build is finished, upload cache information to `_buildcache`
      #
      # For registries that support it, `mode: auto` (the default) will enable the buildkit `mode=max`
      # option.
      #
      # See the following table for details on our detection mechanism:
      #
      # | Registry Name                   | Registry Domain                    | Assumed `mode=max` support |
      # |---------------------------------|------------------------------------|------------------------------|
      # | AWS Elastic Container Registry  | `dkr.ecr.<region>.amazonaws.com` | Yes (with `image-manifest=true`) |
      # | Google Cloud Artifact Registry  | `pkg.dev`                        | Yes                          |
      # | Azure Container Registry        | `azurecr.io`                     | Yes                          |
      # | GitHub Container Registry       | `ghcr.io`                        | Yes                          |
      # | DockerHub                       | `index.docker.io`                | Yes                          |
      # | Any other registry              |                                    | No                           |
      #
      # In case you need to override the defaults for your registry, you can do it like so:
      #
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       mode: max
      #
      # When you add multiple caches, we will make sure to pass the `--import-cache` options to buildkit in the same
      # order as provided in the cache configuration. This is because buildkit will not actually use all imported
      # caches
      # for every build, but it will stick with the first cache that yields a cache hit for all the following layers.
      #
      # An example for this is the following:
      #
      # clusterBuildkit:
      #   cache:
      #     - type: registry
      #       tag: _buildcache-${slice(kebabCase(git.branch), "0", "30")}
      #     - type: registry
      #       tag: _buildcache-main
      #       export: false
      #
      # Using this cache configuration, every build will first look for a cache specific to your feature branch.
      # If it does not exist yet, it will import caches from the main branch builds (`_buildcache-main`).
      # When the build is finished, it will only export caches to your feature branch, and avoid polluting the `main`
      # branch caches.
      # A configuration like that may improve your cache hit rate and thus save time.
      #
      # If you need to disable caches completely you can achieve that with the following configuration:
      #
      # clusterBuildkit:
      #   cache: []
      cache:
        - # Use the Docker registry configured at `deploymentRegistry` to retrieve and store buildkit cache
          # information.
          #
          # See also the [buildkit registry cache
          # documentation](https://github.com/moby/buildkit#registry-push-image-and-cache-separately)
          type:

          # The registry from which the cache should be imported from, or which it should be exported to.
          #
          # If not specified, use the configured `deploymentRegistry` in your kubernetes provider config.
          #
          # Important: You must make sure `imagePullSecrets` includes authentication with the specified cache
          # registry, that has the appropriate write privileges (usually full write access to the configured
          # `namespace`).
          registry:
            # The hostname (and optionally port, if not the default port) of the registry.
            hostname:

            # The port where the registry listens on, if not the default.
            port:

            # The registry namespace. Will be placed between hostname and image name, like so:
            # <hostname>/<namespace>/<image name>
            namespace:

            # Set to true to allow insecure connections to the registry (without SSL).
            insecure: false

          # This is the buildkit cache mode to be used.
          #
          # The value `inline` ensures that garden is using the buildkit option `--export-cache inline`. Cache
          # information will be inlined and co-located with the Docker image itself.
          #
          # The values `min` and `max` ensure that garden passes the `mode=max` or `mode=min` modifiers to the
          # buildkit `--export-cache` option. Cache manifests will only be
          # stored stored in the configured `tag`.
          #
          # `auto` is the same as `max` for some registries that are known to support it. Garden will fall back to
          # `inline` for all other registries.
          #  See the [clusterBuildkit cache option](#providersclusterbuildkitcache) for a description of the detection
          # mechanism.
          #
          # See also the [buildkit export cache documentation](https://github.com/moby/buildkit#export-cache)
          mode: auto

          # This is the Docker registry tag name buildkit should use for the registry build cache. Default is
          # `_buildcache`
          #
          # **NOTE**: `tag` can only be used together with the `registry` cache type
          tag: _buildcache

          # If this is false, only pass the `--import-cache` option to buildkit, and not the `--export-cache` option.
          # Defaults to true.
          export: true

      # Enable rootless mode for the cluster-buildkit daemon, which runs the daemon with decreased privileges.
      # Please see [the buildkit docs](https://github.com/moby/buildkit/blob/master/docs/rootless.md) for caveats when
      # using this mode.
      rootless: false

      # Exposes the `nodeSelector` field on the PodSpec of the BuildKit deployment. This allows you to constrain the
      # BuildKit daemon to only run on particular nodes.
      #
      # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes
      # guide to assigning Pods to nodes.
      nodeSelector: {}

      # Specify tolerations to apply to cluster-buildkit daemon. Useful to control which nodes in a cluster can run
      # builds.
      tolerations:
        - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
          # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
          effect:

          # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
          # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
          key:

          # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
          # Defaults to
          # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
          # particular category.
          operator: Equal

          # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
          # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
          # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
          # by the system.
          tolerationSeconds:

          # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
          # empty,
          # otherwise just a regular string.
          value:

      # Specify annotations to apply to both the Pod and Deployment resources associated with cluster-buildkit.
      # Annotations may have an effect on the behaviour of certain components, for example autoscalers.
      annotations:

      # Specify annotations to apply to the Kubernetes service account used by cluster-buildkit. This can be useful to
      # set up IRSA with in-cluster building.
      serviceAccountAnnotations:

    # Setting related to Jib image builds.
    jib:
      # In some cases you may need to push images built with Jib to the remote registry via Kubernetes cluster, e.g.
      # if you don't have connectivity or access from where Garden is being run. In that case, set this flag to true,
      # but do note that the build will take considerably take longer to complete! Only applies when using in-cluster
      # building.
      pushViaCluster: false

    # Configuration options for the `kaniko` build mode.
    kaniko:
      # Specify extra flags to use when building the container image with kaniko. Flags set on `container` Builds take
      # precedence over these.
      extraFlags:

      # Change the kaniko image (repository/image:tag) to use when building in kaniko mode.
      image: >-
  gcr.io/kaniko-project/executor:v1.11.0-debug@sha256:32ba2214921892c2fa7b5f9c4ae6f8f026538ce6b2105a93a36a8b5ee50fe517

      # Choose the namespace where the Kaniko pods will be run. Defaults to the project namespace.
      namespace:

      # Exposes the `nodeSelector` field on the PodSpec of the Kaniko pods. This allows you to constrain the Kaniko
      # pods to only run on particular nodes. The same nodeSelector will be used for each util pod unless they are
      # specifically set under `util.nodeSelector`.
      #
      # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes
      # guide to assigning pods to nodes.
      nodeSelector:

      # Specify tolerations to apply to each Kaniko builder pod. Useful to control which nodes in a cluster can run
      # builds. The same tolerations will be used for each util pod unless they are specifically set under
      # `util.tolerations`
      tolerations:
        - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
          # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
          effect:

          # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
          # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
          key:

          # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
          # Defaults to
          # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
          # particular category.
          operator: Equal

          # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
          # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
          # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
          # by the system.
          tolerationSeconds:

          # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
          # empty,
          # otherwise just a regular string.
          value:

      # Specify annotations to apply to each Kaniko builder pod. Annotations may have an effect on the behaviour of
      # certain components, for example autoscalers. The same annotations will be used for each util pod unless they
      # are specifically set under `util.annotations`
      annotations:

      # Specify annotations to apply to the Kubernetes service account used by kaniko. This can be useful to set up
      # IRSA with in-cluster building.
      serviceAccountAnnotations:

      util:
        # Specify tolerations to apply to each garden-util pod.
        tolerations:
          - # "Effect" indicates the taint effect to match. Empty means match all taint effects. When specified,
            # allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".
            effect:

            # "Key" is the taint key that the toleration applies to. Empty means match all taint keys.
            # If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.
            key:

            # "Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal".
            # Defaults to
            # "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a
            # particular category.
            operator: Equal

            # "TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute",
            # otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate
            # the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately)
            # by the system.
            tolerationSeconds:

            # "Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be
            # empty,
            # otherwise just a regular string.
            value:

        # Specify annotations to apply to each garden-util pod and deployments.
        annotations:

        # Specify the nodeSelector constraints for each garden-util pod.
        nodeSelector:

    # A default hostname to use when no hostname is explicitly configured for a service.
    defaultHostname:

    # Configuration options for code synchronization.
    sync:
      # Specifies default settings for syncs (e.g. for `container`, `kubernetes` and `helm` services).
      #
      # These are overridden/extended by the settings of any individual sync specs.
      #
      # Sync is enabled e.g by setting the `--sync` flag on the `garden deploy` command.
      #
      # See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for more
      # information.
      defaults:
        # Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.
        #
        # Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.
        #
        # `.git` directories and `.garden` directories are always ignored.
        exclude:

        # The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644
        # (user can read/write, everyone else can read). See the [Mutagen
        # docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.
        fileMode: 420

        # The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to
        # 0o755 (user can read/write, everyone else can read). See the [Mutagen
        # docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.
        directoryMode: 493

        # Set the default owner of files and directories at the target. Specify either an integer ID or a string name.
        # See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for
        # more information.
        owner:

        # Set the default group on files and directories at the target. Specify either an integer ID or a string name.
        # See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for
        # more information.
        group:

    # Require SSL on all `container` Deploys. If set to true, an error is raised when no certificate is available for
    # a configured hostname on a `container`Deploy.
    forceSsl: false

    # References to `docker-registry` secrets to use for authenticating with remote registries when pulling
    # images. This is necessary if you reference private images in your action configuration, and is required
    # when configuring a remote Kubernetes environment with buildMode=local.
    imagePullSecrets:
      - # The name of the Kubernetes secret.
        name:

        # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
        # namespace before use.
        namespace: default

    # References to secrets you need to have copied into all namespaces deployed to. These secrets will be
    # ensured to exist in the namespace before deploying any service.
    copySecrets:
      - # The name of the Kubernetes secret.
        name:

        # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
        # namespace before use.
        namespace: default

    # Resource requests and limits for the in-cluster builder..
    resources:
      # Resource requests and limits for the in-cluster builder. It's important to consider which build mode you're
      # using when configuring this.
      #
      # When `buildMode` is `kaniko`, this refers to _each Kaniko pod_, i.e. each individual build, so you'll want to
      # consider the requirements for your individual image builds, with your most expensive/heavy images in mind.
      #
      # When `buildMode` is `cluster-buildkit`, this applies to the BuildKit deployment created in _each project
      # namespace_. So think of this as the resource spec for each individual user or project namespace.
      builder:
        limits:
          # CPU limit in millicpu.
          cpu: 4000

          # Memory limit in megabytes.
          memory: 8192

          # Ephemeral storage limit in megabytes.
          ephemeralStorage:

        requests:
          # CPU request in millicpu.
          cpu: 100

          # Memory request in megabytes.
          memory: 512

          # Ephemeral storage request in megabytes.
          ephemeralStorage:

      # Resource requests and limits for the util pod for in-cluster builders.
      # This pod is used to get, start, stop and inquire the status of the builds.
      #
      # This pod is created in each garden namespace.
      util:
        limits:
          # CPU limit in millicpu.
          cpu: 256

          # Memory limit in megabytes.
          memory: 512

          # Ephemeral storage limit in megabytes.
          ephemeralStorage:

        requests:
          # CPU request in millicpu.
          cpu: 256

          # Memory request in megabytes.
          memory: 512

          # Ephemeral storage request in megabytes.
          ephemeralStorage:

    # One or more certificates to use for ingress.
    tlsCertificates:
      - # A unique identifier for this certificate.
        name:

        # A list of hostnames that this certificate should be used for. If you don't specify these, they will be
        # automatically read from the certificate.
        hostnames:

        # A reference to the Kubernetes secret that contains the TLS certificate and key for the domain.
        secretRef:
          # The name of the Kubernetes secret.
          name:

          # The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate
          # namespace before use.
          namespace: default

    # Exposes the `nodeSelector` field on the PodSpec of system services. This allows you to constrain the system
    # services to only run on particular nodes.
    #
    # [See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide
    # to assigning Pods to nodes.
    systemNodeSelector: {}

    # The name of the provider plugin to use.
    name: local-kubernetes

    # The kubectl context to use to connect to the Kubernetes cluster.
    context:

    # Specify which namespace to deploy services to (defaults to the project name). Note that the framework generates
    # other namespaces as well with this name as a prefix.
    namespace:
      # A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters,
      # numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63
      # characters.
      name:

      # Map of annotations to apply to the namespace when creating it.
      annotations:

      # Map of labels to apply to the namespace when creating it.
      labels:

    # Set this to `nginx` or `traefik` to install the respective ingress controller, or to `null`/`false` to skip. The
    # nginx controller is deprecated and will be removed in a future version — we recommend switching to `traefik`.
    setupIngressController: nginx
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].utilImageRegistryDomain`

[providers](#providers) > utilImageRegistryDomain

The container registry domain that should be used for pulling Garden utility images (such as the image used in the Kubernetes sync utility Pod).

If you have your own Docker Hub registry mirror, you can set the domain here and the utility images will be pulled from there. This can be useful to e.g. avoid Docker Hub rate limiting.

Otherwise the utility images are pulled directly from Docker Hub by default.

| Type     | Default       | Required |
| -------- | ------------- | -------- |
| `string` | `"docker.io"` | No       |

### `providers[].buildMode`

[providers](#providers) > buildMode

Choose the mechanism for building container images before deploying. By default your local Docker daemon is used, but you can set it to `cluster-buildkit` or `kaniko` to sync files to the cluster, and build container images there. This removes the need to run Docker locally, and allows you to share layer and image caches between multiple developers, as well as between your development and CI workflows.

For more details on all the different options and what makes sense to use for your setup, please check out the [in-cluster building guide](https://docs.garden.io/cedar-0.14/kubernetes-plugins/guides/in-cluster-building).

| Type     | Allowed Values                               | Default          | Required |
| -------- | -------------------------------------------- | ---------------- | -------- |
| `string` | "local-docker", "kaniko", "cluster-buildkit" | `"local-docker"` | Yes      |

### `providers[].clusterBuildkit`

[providers](#providers) > clusterBuildkit

Configuration options for the `cluster-buildkit` build mode.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `providers[].clusterBuildkit.cache[]`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > cache

Use the `cache` configuration to customize the default cluster-buildkit cache behaviour.

The default value is:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      mode: auto
```

For every build, this will

* import cached layers from a docker image tag named `_buildcache`
* when the build is finished, upload cache information to `_buildcache`

For registries that support it, `mode: auto` (the default) will enable the buildkit `mode=max` option.

See the following table for details on our detection mechanism:

| Registry Name                  | Registry Domain                  | Assumed `mode=max` support       |
| ------------------------------ | -------------------------------- | -------------------------------- |
| AWS Elastic Container Registry | `dkr.ecr.<region>.amazonaws.com` | Yes (with `image-manifest=true`) |
| Google Cloud Artifact Registry | `pkg.dev`                        | Yes                              |
| Azure Container Registry       | `azurecr.io`                     | Yes                              |
| GitHub Container Registry      | `ghcr.io`                        | Yes                              |
| DockerHub                      | `index.docker.io`                | Yes                              |
| Any other registry             |                                  | No                               |

In case you need to override the defaults for your registry, you can do it like so:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      mode: max
```

When you add multiple caches, we will make sure to pass the `--import-cache` options to buildkit in the same order as provided in the cache configuration. This is because buildkit will not actually use all imported caches for every build, but it will stick with the first cache that yields a cache hit for all the following layers.

An example for this is the following:

```yaml
clusterBuildkit:
  cache:
    - type: registry
      tag: _buildcache-${slice(kebabCase(git.branch), "0", "30")}
    - type: registry
      tag: _buildcache-main
      export: false
```

Using this cache configuration, every build will first look for a cache specific to your feature branch. If it does not exist yet, it will import caches from the main branch builds (`_buildcache-main`). When the build is finished, it will only export caches to your feature branch, and avoid polluting the `main` branch caches. A configuration like that may improve your cache hit rate and thus save time.

If you need to disable caches completely you can achieve that with the following configuration:

```yaml
clusterBuildkit:
  cache: []
```

| Type            | Default                                                                 | Required |
| --------------- | ----------------------------------------------------------------------- | -------- |
| `array[object]` | `[{"type":"registry","mode":"auto","tag":"_buildcache","export":true}]` | No       |

### `providers[].clusterBuildkit.cache[].type`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > type

Use the Docker registry configured at `deploymentRegistry` to retrieve and store buildkit cache information.

See also the [buildkit registry cache documentation](https://github.com/moby/buildkit#registry-push-image-and-cache-separately)

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "registry"     | Yes      |

### `providers[].clusterBuildkit.cache[].registry`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > registry

The registry from which the cache should be imported from, or which it should be exported to.

If not specified, use the configured `deploymentRegistry` in your kubernetes provider config.

Important: You must make sure `imagePullSecrets` includes authentication with the specified cache registry, that has the appropriate write privileges (usually full write access to the configured `namespace`).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].clusterBuildkit.cache[].registry.hostname`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > hostname

The hostname (and optionally port, if not the default port) of the registry.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      cache:
        - registry:
            ...
            hostname: "gcr.io"
```

### `providers[].clusterBuildkit.cache[].registry.port`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > port

The port where the registry listens on, if not the default.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `providers[].clusterBuildkit.cache[].registry.namespace`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > namespace

The registry namespace. Will be placed between hostname and image name, like so: //

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      cache:
        - registry:
            ...
            namespace: "my-project"
```

### `providers[].clusterBuildkit.cache[].registry.insecure`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > [registry](#providersclusterbuildkitcacheregistry) > insecure

Set to true to allow insecure connections to the registry (without SSL).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].clusterBuildkit.cache[].mode`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > mode

This is the buildkit cache mode to be used.

The value `inline` ensures that garden is using the buildkit option `--export-cache inline`. Cache information will be inlined and co-located with the Docker image itself.

The values `min` and `max` ensure that garden passes the `mode=max` or `mode=min` modifiers to the buildkit `--export-cache` option. Cache manifests will only be stored stored in the configured `tag`.

`auto` is the same as `max` for some registries that are known to support it. Garden will fall back to `inline` for all other registries. See the [clusterBuildkit cache option](#providersclusterbuildkitcache) for a description of the detection mechanism.

See also the [buildkit export cache documentation](https://github.com/moby/buildkit#export-cache)

| Type     | Allowed Values                 | Default  | Required |
| -------- | ------------------------------ | -------- | -------- |
| `string` | "auto", "min", "max", "inline" | `"auto"` | Yes      |

### `providers[].clusterBuildkit.cache[].tag`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > tag

This is the Docker registry tag name buildkit should use for the registry build cache. Default is `_buildcache`

**NOTE**: `tag` can only be used together with the `registry` cache type

| Type     | Default         | Required |
| -------- | --------------- | -------- |
| `string` | `"_buildcache"` | No       |

### `providers[].clusterBuildkit.cache[].export`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [cache](#providersclusterbuildkitcache) > export

If this is false, only pass the `--import-cache` option to buildkit, and not the `--export-cache` option. Defaults to true.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `providers[].clusterBuildkit.rootless`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > rootless

Enable rootless mode for the cluster-buildkit daemon, which runs the daemon with decreased privileges. Please see [the buildkit docs](https://github.com/moby/buildkit/blob/master/docs/rootless.md) for caveats when using this mode.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].clusterBuildkit.nodeSelector`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > nodeSelector

Exposes the `nodeSelector` field on the PodSpec of the BuildKit deployment. This allows you to constrain the BuildKit daemon to only run on particular nodes.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning Pods to nodes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      nodeSelector:
          disktype: ssd
```

### `providers[].clusterBuildkit.tolerations[]`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > tolerations

Specify tolerations to apply to cluster-buildkit daemon. Useful to control which nodes in a cluster can run builds.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].clusterBuildkit.tolerations[].effect`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].key`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].operator`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].clusterBuildkit.tolerations[].tolerationSeconds`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.tolerations[].value`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > [tolerations](#providersclusterbuildkittolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].clusterBuildkit.annotations`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > annotations

Specify annotations to apply to both the Pod and Deployment resources associated with cluster-buildkit. Annotations may have an effect on the behaviour of certain components, for example autoscalers.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].clusterBuildkit.serviceAccountAnnotations`

[providers](#providers) > [clusterBuildkit](#providersclusterbuildkit) > serviceAccountAnnotations

Specify annotations to apply to the Kubernetes service account used by cluster-buildkit. This can be useful to set up IRSA with in-cluster building.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - clusterBuildkit:
      ...
      serviceAccountAnnotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
```

### `providers[].jib`

[providers](#providers) > jib

Setting related to Jib image builds.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].jib.pushViaCluster`

[providers](#providers) > [jib](#providersjib) > pushViaCluster

In some cases you may need to push images built with Jib to the remote registry via Kubernetes cluster, e.g. if you don't have connectivity or access from where Garden is being run. In that case, set this flag to true, but do note that the build will take considerably take longer to complete! Only applies when using in-cluster building.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].kaniko`

[providers](#providers) > kaniko

Configuration options for the `kaniko` build mode.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.extraFlags[]`

[providers](#providers) > [kaniko](#providerskaniko) > extraFlags

Specify extra flags to use when building the container image with kaniko. Flags set on `container` Builds take precedence over these.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `providers[].kaniko.image`

[providers](#providers) > [kaniko](#providerskaniko) > image

Change the kaniko image (repository/image:tag) to use when building in kaniko mode.

| Type     | Default                                                                                                                  | Required |
| -------- | ------------------------------------------------------------------------------------------------------------------------ | -------- |
| `string` | `"gcr.io/kaniko-project/executor:v1.11.0-debug@sha256:32ba2214921892c2fa7b5f9c4ae6f8f026538ce6b2105a93a36a8b5ee50fe517"` | No       |

### `providers[].kaniko.namespace`

[providers](#providers) > [kaniko](#providerskaniko) > namespace

Choose the namespace where the Kaniko pods will be run. Defaults to the project namespace.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.nodeSelector`

[providers](#providers) > [kaniko](#providerskaniko) > nodeSelector

Exposes the `nodeSelector` field on the PodSpec of the Kaniko pods. This allows you to constrain the Kaniko pods to only run on particular nodes. The same nodeSelector will be used for each util pod unless they are specifically set under `util.nodeSelector`.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning pods to nodes.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.tolerations[]`

[providers](#providers) > [kaniko](#providerskaniko) > tolerations

Specify tolerations to apply to each Kaniko builder pod. Useful to control which nodes in a cluster can run builds. The same tolerations will be used for each util pod unless they are specifically set under `util.tolerations`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].kaniko.tolerations[].effect`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].key`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].operator`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].kaniko.tolerations[].tolerationSeconds`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.tolerations[].value`

[providers](#providers) > [kaniko](#providerskaniko) > [tolerations](#providerskanikotolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.annotations`

[providers](#providers) > [kaniko](#providerskaniko) > annotations

Specify annotations to apply to each Kaniko builder pod. Annotations may have an effect on the behaviour of certain components, for example autoscalers. The same annotations will be used for each util pod unless they are specifically set under `util.annotations`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].kaniko.serviceAccountAnnotations`

[providers](#providers) > [kaniko](#providerskaniko) > serviceAccountAnnotations

Specify annotations to apply to the Kubernetes service account used by kaniko. This can be useful to set up IRSA with in-cluster building.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      serviceAccountAnnotations:
          eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
```

### `providers[].kaniko.util`

[providers](#providers) > [kaniko](#providerskaniko) > util

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].kaniko.util.tolerations[]`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > tolerations

Specify tolerations to apply to each garden-util pod.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].kaniko.util.tolerations[].effect`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > effect

"Effect" indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are "NoSchedule", "PreferNoSchedule" and "NoExecute".

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].key`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > key

"Key" is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be "Exists"; this combination means to match all values and all keys.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].operator`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > operator

"Operator" represents a key's relationship to the value. Valid operators are "Exists" and "Equal". Defaults to "Equal". "Exists" is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"Equal"` | No       |

### `providers[].kaniko.util.tolerations[].tolerationSeconds`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > tolerationSeconds

"TolerationSeconds" represents the period of time the toleration (which must be of effect "NoExecute", otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.tolerations[].value`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > [tolerations](#providerskanikoutiltolerations) > value

"Value" is the taint value the toleration matches to. If the operator is "Exists", the value should be empty, otherwise just a regular string.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].kaniko.util.annotations`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > annotations

Specify annotations to apply to each garden-util pod and deployments.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - kaniko:
      ...
      util:
        ...
        annotations:
            cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].kaniko.util.nodeSelector`

[providers](#providers) > [kaniko](#providerskaniko) > [util](#providerskanikoutil) > nodeSelector

Specify the nodeSelector constraints for each garden-util pod.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].defaultHostname`

[providers](#providers) > defaultHostname

A default hostname to use when no hostname is explicitly configured for a service.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - defaultHostname: "api.mydomain.com"
```

### `providers[].sync`

[providers](#providers) > sync

Configuration options for code synchronization.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].sync.defaults`

[providers](#providers) > [sync](#providerssync) > defaults

Specifies default settings for syncs (e.g. for `container`, `kubernetes` and `helm` services).

These are overridden/extended by the settings of any individual sync specs.

Sync is enabled e.g by setting the `--sync` flag on the `garden deploy` command.

See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for more information.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].sync.defaults.exclude[]`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
providers:
  - sync:
      ...
      defaults:
        ...
        exclude:
          - dist/**/*
          - '*.log'
```

### `providers[].sync.defaults.fileMode`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > fileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `providers[].sync.defaults.directoryMode`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > directoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `providers[].sync.defaults.owner`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > owner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `providers[].sync.defaults.group`

[providers](#providers) > [sync](#providerssync) > [defaults](#providerssyncdefaults) > group

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `providers[].forceSsl`

[providers](#providers) > forceSsl

Require SSL on all `container` Deploys. If set to true, an error is raised when no certificate is available for a configured hostname on a `container`Deploy.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].imagePullSecrets[]`

[providers](#providers) > imagePullSecrets

References to `docker-registry` secrets to use for authenticating with remote registries when pulling images. This is necessary if you reference private images in your action configuration, and is required when configuring a remote Kubernetes environment with buildMode=local.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].imagePullSecrets[].name`

[providers](#providers) > [imagePullSecrets](#providersimagepullsecrets) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - imagePullSecrets:
      - name: "my-secret"
```

### `providers[].imagePullSecrets[].namespace`

[providers](#providers) > [imagePullSecrets](#providersimagepullsecrets) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].copySecrets[]`

[providers](#providers) > copySecrets

References to secrets you need to have copied into all namespaces deployed to. These secrets will be ensured to exist in the namespace before deploying any service.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].copySecrets[].name`

[providers](#providers) > [copySecrets](#providerscopysecrets) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - copySecrets:
      - name: "my-secret"
```

### `providers[].copySecrets[].namespace`

[providers](#providers) > [copySecrets](#providerscopysecrets) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].resources`

[providers](#providers) > resources

Resource requests and limits for the in-cluster builder..

| Type     | Default                                                                                                                                                                | Required |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `object` | `{"builder":{"limits":{"cpu":4000,"memory":8192},"requests":{"cpu":100,"memory":512}},"util":{"limits":{"cpu":256,"memory":512},"requests":{"cpu":256,"memory":512}}}` | No       |

### `providers[].resources.builder`

[providers](#providers) > [resources](#providersresources) > builder

Resource requests and limits for the in-cluster builder. It's important to consider which build mode you're using when configuring this.

When `buildMode` is `kaniko`, this refers to *each Kaniko pod*, i.e. each individual build, so you'll want to consider the requirements for your individual image builds, with your most expensive/heavy images in mind.

When `buildMode` is `cluster-buildkit`, this applies to the BuildKit deployment created in *each project namespace*. So think of this as the resource spec for each individual user or project namespace.

| Type     | Default                                                                     | Required |
| -------- | --------------------------------------------------------------------------- | -------- |
| `object` | `{"limits":{"cpu":4000,"memory":8192},"requests":{"cpu":100,"memory":512}}` | No       |

### `providers[].resources.builder.limits`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > limits

| Type     | Default                      | Required |
| -------- | ---------------------------- | -------- |
| `object` | `{"cpu":4000,"memory":8192}` | No       |

### `providers[].resources.builder.limits.cpu`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > cpu

CPU limit in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `4000`  | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          cpu: 4000
```

### `providers[].resources.builder.limits.memory`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > memory

Memory limit in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `8192`  | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          memory: 8192
```

### `providers[].resources.builder.limits.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [limits](#providersresourcesbuilderlimits) > ephemeralStorage

Ephemeral storage limit in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        limits:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.builder.requests`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > requests

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":100,"memory":512}` | No       |

### `providers[].resources.builder.requests.cpu`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > cpu

CPU request in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `100`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          cpu: 100
```

### `providers[].resources.builder.requests.memory`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > memory

Memory request in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          memory: 512
```

### `providers[].resources.builder.requests.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [builder](#providersresourcesbuilder) > [requests](#providersresourcesbuilderrequests) > ephemeralStorage

Ephemeral storage request in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      builder:
        ...
        requests:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.util`

[providers](#providers) > [resources](#providersresources) > util

Resource requests and limits for the util pod for in-cluster builders. This pod is used to get, start, stop and inquire the status of the builds.

This pod is created in each garden namespace.

| Type     | Default                                                                   | Required |
| -------- | ------------------------------------------------------------------------- | -------- |
| `object` | `{"limits":{"cpu":256,"memory":512},"requests":{"cpu":256,"memory":512}}` | No       |

### `providers[].resources.util.limits`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > limits

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":256,"memory":512}` | No       |

### `providers[].resources.util.limits.cpu`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > cpu

CPU limit in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `256`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          cpu: 256
```

### `providers[].resources.util.limits.memory`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > memory

Memory limit in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          memory: 512
```

### `providers[].resources.util.limits.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [limits](#providersresourcesutillimits) > ephemeralStorage

Ephemeral storage limit in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        limits:
          ...
          ephemeralStorage: 8192
```

### `providers[].resources.util.requests`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > requests

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `object` | `{"cpu":256,"memory":512}` | No       |

### `providers[].resources.util.requests.cpu`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > cpu

CPU request in millicpu.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `256`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          cpu: 256
```

### `providers[].resources.util.requests.memory`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > memory

Memory request in megabytes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `512`   | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          memory: 512
```

### `providers[].resources.util.requests.ephemeralStorage`

[providers](#providers) > [resources](#providersresources) > [util](#providersresourcesutil) > [requests](#providersresourcesutilrequests) > ephemeralStorage

Ephemeral storage request in megabytes.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
providers:
  - resources:
      ...
      util:
        ...
        requests:
          ...
          ephemeralStorage: 8192
```

### `providers[].tlsCertificates[]`

[providers](#providers) > tlsCertificates

One or more certificates to use for ingress.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].tlsCertificates[].name`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > name

A unique identifier for this certificate.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - name: "www"
```

### `providers[].tlsCertificates[].hostnames[]`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > hostnames

A list of hostnames that this certificate should be used for. If you don't specify these, they will be automatically read from the certificate.

| Type              | Required |
| ----------------- | -------- |
| `array[hostname]` | No       |

Example:

```yaml
providers:
  - tlsCertificates:
      - hostnames:
          - www.mydomain.com
```

### `providers[].tlsCertificates[].secretRef`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > secretRef

A reference to the Kubernetes secret that contains the TLS certificate and key for the domain.

| Type     | Required |
| -------- | -------- |
| `object` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - secretRef:
            name: my-tls-secret
            namespace: default
```

### `providers[].tlsCertificates[].secretRef.name`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > [secretRef](#providerstlscertificatessecretref) > name

The name of the Kubernetes secret.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - tlsCertificates:
      - secretRef:
            name: my-tls-secret
            namespace: default
          ...
          name: "my-secret"
```

### `providers[].tlsCertificates[].secretRef.namespace`

[providers](#providers) > [tlsCertificates](#providerstlscertificates) > [secretRef](#providerstlscertificatessecretref) > namespace

The namespace where the secret is stored. If necessary, the secret may be copied to the appropriate namespace before use.

| Type     | Default     | Required |
| -------- | ----------- | -------- |
| `string` | `"default"` | No       |

### `providers[].systemNodeSelector`

[providers](#providers) > systemNodeSelector

Exposes the `nodeSelector` field on the PodSpec of system services. This allows you to constrain the system services to only run on particular nodes.

[See here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) for the official Kubernetes guide to assigning Pods to nodes.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
providers:
  - systemNodeSelector:
        disktype: ssd
```

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Default              | Required |
| -------- | -------------------- | -------- |
| `string` | `"local-kubernetes"` | Yes      |

Example:

```yaml
providers:
  - name: "local-kubernetes"
```

### `providers[].context`

[providers](#providers) > context

The kubectl context to use to connect to the Kubernetes cluster.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
providers:
  - context: "my-dev-context"
```

### `providers[].namespace`

[providers](#providers) > namespace

Specify which namespace to deploy services to (defaults to the project name). Note that the framework generates other namespaces as well with this name as a prefix.

| Type               | Required |
| ------------------ | -------- |
| `object \| string` | No       |

### `providers[].namespace.name`

[providers](#providers) > [namespace](#providersnamespace) > name

A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63 characters.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].namespace.annotations`

[providers](#providers) > [namespace](#providersnamespace) > annotations

Map of annotations to apply to the namespace when creating it.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - namespace: ''
      ...
      annotations:
          cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'
```

### `providers[].namespace.labels`

[providers](#providers) > [namespace](#providersnamespace) > labels

Map of labels to apply to the namespace when creating it.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].setupIngressController`

[providers](#providers) > setupIngressController

Set this to `nginx` or `traefik` to install the respective ingress controller, or to `null`/`false` to skip. The nginx controller is deprecated and will be removed in a future version — we recommend switching to `traefik`.

| Type     | Default   | Required |
| -------- | --------- | -------- |
| `string` | `"nginx"` | No       |

## Outputs

The following keys are available via the `${providers.<provider-name>}` template string key for `local-kubernetes` providers.

### `${providers.<provider-name>.outputs.app-namespace}`

The primary namespace used for resource deployments.

| Type     |
| -------- |
| `string` |

### `${providers.<provider-name>.outputs.default-hostname}`

The default hostname configured on the provider.

| Type     |
| -------- |
| `string` |


# otel-collector

## Description

This provider enables gathering and exporting [OpenTelemetry](https://opentelemetry.io/) data for the Garden execution.

It provides detailed insights into what a Garden command is doing at any given time and can be used for alerting on performance regressions or debugging performance issues.

It does that by running an [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector) on the local machine for the duration of the command execution, which then exports the gathered data to the desired service.

Currently supported exporters are [Datadog](https://www.datadoghq.com/), [Newrelic](https://newrelic.com/), [Honeycomb](https://www.honeycomb.io/) and 'OTLP HTTP'.

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    #
    # Example: `["exec"]`
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    #
    # Example: `["dev","stage"]`
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    exporters:
      - name:

        enabled:

        verbosity: normal
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

Example: `["exec"]`

| Type    | Default | Required |
| ------- | ------- | -------- |
| `array` | `[]`    | No       |

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

Example: `["dev","stage"]`

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].exporters[]`

[providers](#providers) > exporters

| Type    | Required |
| ------- | -------- |
| `array` | Yes      |

### `providers[].exporters[].name`

[providers](#providers) > [exporters](#providersexporters) > name

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].exporters[].enabled`

[providers](#providers) > [exporters](#providersexporters) > enabled

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `providers[].exporters[].verbosity`

[providers](#providers) > [exporters](#providersexporters) > verbosity

| Type     | Allowed Values                | Default    | Required |
| -------- | ----------------------------- | ---------- | -------- |
| `string` | "detailed", "normal", "basic" | `"normal"` | No       |


# pulumi

## Description

**EXPERIMENTAL**

This provider allows you to integrate [Pulumi](https://pulumi.com) stacks into your Garden project, via [`pulumi` Deploy actions](/reference/action-types/deploy/pulumi).

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # The version of pulumi to use. Set to `null` to use whichever version of `pulumi` is on your PATH, or provide
    # an absolute path to a terraform binary.
    version: 3.122.0

    # Overrides the default plan directory path used when deploying with the `deployFromPreview` option for pulumi
    # deploy actions.
    #
    # Must be a relative path to a directory inside the project root.
    #
    # This option can be useful when you want to provide a folder of pre-approved pulumi plans to a CI pipeline step.
    previewDir:

    # The name of the pulumi organization to use. This option can also be set on the deploy action level, in which
    # case it
    # overrides this provider-level option. Note that setting the organization name is only necessary when using
    # pulumi managed backend with an organization.
    orgName:

    # The URL of the state backend endpoint used. This option can also be set on the deploy action level, in which
    # case it
    # overrides this  provider-level option. Set this option as per list of available self-managed state backends on
    # https://www.pulumi.com/docs/intro/concepts/state/#using-a-self-managed-backend
    backendURL: https://api.pulumi.com

    # Sets the maximum task concurrency for the tasks generated by the pulumi plugin commands (e.g. when running
    # `garden plugins pulumi preview`).
    #
    # Note: This limit is not applied when running built-in commands (e.g. `garden deploy`).
    pluginTaskConcurrencyLimit: 5

    # If set to true, the deploy action will use the new Pulumi varfile schema, which does not nest all variables
    # under
    # the 'config' key automatically like the old schema. This allow setting variables at the root level of the
    # varfile
    # that don't belong to the 'config' key. Example:
    # config:
    #   myVar: value
    # secretsprovider: gcpkms://projects/xyz/locations/global/keyRings/pulumi/cryptoKeys/pulumi-secrets
    # For more information see [this guide on pulumi varfiles and
    # variables](https://docs.garden.io/pulumi-plugin/about#pulumi-varfile-schema)
    useNewPulumiVarfileSchema: false
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - name: "local-kubernetes"
```

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].version`

[providers](#providers) > version

The version of pulumi to use. Set to `null` to use whichever version of `pulumi` is on your PATH, or provide an absolute path to a terraform binary.

| Type                         | Default     | Required |
| ---------------------------- | ----------- | -------- |
| `string \| posixPath \| any` | `"3.122.0"` | No       |

### `providers[].previewDir`

[providers](#providers) > previewDir

Overrides the default plan directory path used when deploying with the `deployFromPreview` option for pulumi deploy actions.

Must be a relative path to a directory inside the project root.

This option can be useful when you want to provide a folder of pre-approved pulumi plans to a CI pipeline step.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `providers[].orgName`

[providers](#providers) > orgName

The name of the pulumi organization to use. This option can also be set on the deploy action level, in which case it overrides this provider-level option. Note that setting the organization name is only necessary when using pulumi managed backend with an organization.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].backendURL`

[providers](#providers) > backendURL

The URL of the state backend endpoint used. This option can also be set on the deploy action level, in which case it overrides this provider-level option. Set this option as per list of available self-managed state backends on <https://www.pulumi.com/docs/intro/concepts/state/#using-a-self-managed-backend>

| Type     | Default                    | Required |
| -------- | -------------------------- | -------- |
| `string` | `"https://api.pulumi.com"` | No       |

### `providers[].pluginTaskConcurrencyLimit`

[providers](#providers) > pluginTaskConcurrencyLimit

Sets the maximum task concurrency for the tasks generated by the pulumi plugin commands (e.g. when running `garden plugins pulumi preview`).

Note: This limit is not applied when running built-in commands (e.g. `garden deploy`).

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `5`     | No       |

### `providers[].useNewPulumiVarfileSchema`

[providers](#providers) > useNewPulumiVarfileSchema

If set to true, the deploy action will use the new Pulumi varfile schema, which does not nest all variables under the 'config' key automatically like the old schema. This allow setting variables at the root level of the varfile that don't belong to the 'config' key. Example:

```
config:
  myVar: value
secretsprovider: gcpkms://projects/xyz/locations/global/keyRings/pulumi/cryptoKeys/pulumi-secrets
```

For more information see [this guide on pulumi varfiles and variables](https://docs.garden.io/pulumi-plugin/about#pulumi-varfile-schema)

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |


# terraform

## Description

This provider allows you to integrate Terraform stacks into your Garden project. See the [Terraform guide](https://docs.garden.io/cedar-0.14/advanced/terraform) for details and usage information.

Below is the full schema reference for the provider configuration..

The reference is divided into two sections. The [first section](#complete-yaml-schema) contains the complete YAML schema, and the [second section](#configuration-keys) describes each schema key.

## Complete YAML Schema

The values in the schema below are the default values.

```yaml
providers:
  - # The name of the provider plugin to use.
    name:

    # List other providers that should be resolved before this one.
    dependencies: []

    # If specified, this provider will only be used in the listed environments. Note that an empty array effectively
    # disables the provider. To use a provider in all environments, omit this field.
    environments:

    preInit:
      # A script to run before the provider is initialized. This is useful for performing any provider-specific setup
      # outside of Garden. For example, you can use this to perform authentication, such as authenticating with a
      # Kubernetes cluster provider.
      # The script will always be run from the project root directory.
      # Note that provider statuses are cached, so this script will generally only be run once, but you can force a
      # re-run by setting `--force-refresh` on any Garden command that uses the provider.
      runScript:

    # If set to true, Garden will run `terraform destroy` on the project root stack when calling `garden delete env`.
    allowDestroy: false

    # If set to true, Garden will automatically run `terraform apply -auto-approve` when a stack is not up-to-date.
    # Otherwise, a warning is logged if the stack is out-of-date, and an error thrown if it is missing entirely.
    #
    # **Note: This is not recommended for production, or shared environments in general!**
    autoApply: false

    # Specify the path to a Terraform config directory, that should be resolved when initializing the provider. This
    # is useful when other providers need to be able to reference the outputs from the stack.
    #
    # See the [Terraform guide](https://docs.garden.io/cedar-0.14/advanced/terraform) for more information.
    initRoot:

    # A map of variables to use when applying Terraform stacks. You can define these here, in individual
    # `terraform` action configs, or you can place a `terraform.tfvars` file in each working directory.
    variables:

    # The version of Terraform to use. Set to `null` to use the version of `terraform` that is on your PATH, or
    # provide an absolute path to a terraform binary.
    version: 1.4.6

    # Use the specified Terraform workspace.
    workspace:

    # Set to `true` to make logs from Terraform Deploy actions visible in Garden Cloud/Enterprise. Defaults to `false`
    streamLogsToCloud: false

    # Configure the Terraform backend.
    #
    # The key-value pairs defined here are set as the `-backend-config` options when Garden
    # runs `terraform init`.
    #
    # This can be used to dynamically set a Terraform backend depending on the environment.
    #
    # If Garden sees that the backend has changes, it'll re-initialize Terraform and set the new values.
    backendConfig:
```

## Configuration Keys

### `providers[]`

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `providers[].name`

[providers](#providers) > name

The name of the provider plugin to use.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

Example:

```yaml
providers:
  - name: "local-kubernetes"
```

### `providers[].dependencies[]`

[providers](#providers) > dependencies

List other providers that should be resolved before this one.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
providers:
  - dependencies:
      - exec
```

### `providers[].environments[]`

[providers](#providers) > environments

If specified, this provider will only be used in the listed environments. Note that an empty array effectively disables the provider. To use a provider in all environments, omit this field.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
providers:
  - environments:
      - dev
      - stage
```

### `providers[].preInit`

[providers](#providers) > preInit

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].preInit.runScript`

[providers](#providers) > [preInit](#providerspreinit) > runScript

A script to run before the provider is initialized. This is useful for performing any provider-specific setup outside of Garden. For example, you can use this to perform authentication, such as authenticating with a Kubernetes cluster provider. The script will always be run from the project root directory. Note that provider statuses are cached, so this script will generally only be run once, but you can force a re-run by setting `--force-refresh` on any Garden command that uses the provider.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].allowDestroy`

[providers](#providers) > allowDestroy

If set to true, Garden will run `terraform destroy` on the project root stack when calling `garden delete env`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].autoApply`

[providers](#providers) > autoApply

If set to true, Garden will automatically run `terraform apply -auto-approve` when a stack is not up-to-date. Otherwise, a warning is logged if the stack is out-of-date, and an error thrown if it is missing entirely.

**Note: This is not recommended for production, or shared environments in general!**

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].initRoot`

[providers](#providers) > initRoot

Specify the path to a Terraform config directory, that should be resolved when initializing the provider. This is useful when other providers need to be able to reference the outputs from the stack.

See the [Terraform guide](https://docs.garden.io/cedar-0.14/advanced/terraform) for more information.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `providers[].variables`

[providers](#providers) > variables

A map of variables to use when applying Terraform stacks. You can define these here, in individual `terraform` action configs, or you can place a `terraform.tfvars` file in each working directory.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `providers[].version`

[providers](#providers) > version

The version of Terraform to use. Set to `null` to use the version of `terraform` that is on your PATH, or provide an absolute path to a terraform binary.

| Type                         | Default   | Required |
| ---------------------------- | --------- | -------- |
| `string \| posixPath \| any` | `"1.4.6"` | No       |

### `providers[].workspace`

[providers](#providers) > workspace

Use the specified Terraform workspace.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `providers[].streamLogsToCloud`

[providers](#providers) > streamLogsToCloud

Set to `true` to make logs from Terraform Deploy actions visible in Garden Cloud/Enterprise. Defaults to `false`

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `providers[].backendConfig`

[providers](#providers) > backendConfig

Configure the Terraform backend.

The key-value pairs defined here are set as the `-backend-config` options when Garden runs `terraform init`.

This can be used to dynamically set a Terraform backend depending on the environment.

If Garden sees that the backend has changes, it'll re-initialize Terraform and set the new values.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
providers:
  - backendConfig:
        bucket: ${environment.name}-bucket
        key: tf-state/${local.username}/terraform.tfstate
```


# Action Types

* [Build](/reference/action-types/build)
  * [`container`](/reference/action-types/build/container)
  * [`jib-container`](/reference/action-types/build/jib-container)
  * [`exec`](/reference/action-types/build/exec)
* [Deploy](/reference/action-types/deploy)
  * [`container`](/reference/action-types/deploy/container)
  * [`kubernetes`](/reference/action-types/deploy/kubernetes)
  * [`helm`](/reference/action-types/deploy/helm)
  * [`exec`](/reference/action-types/deploy/exec)
  * [`terraform`](/reference/action-types/deploy/terraform)
  * [`pulumi`](/reference/action-types/deploy/pulumi)
* [Run](/reference/action-types/run)
  * [`container`](/reference/action-types/run/container)
  * [`kubernetes-exec`](/reference/action-types/run/kubernetes-exec)
  * [`kubernetes-pod`](/reference/action-types/run/kubernetes-pod)
  * [`helm-pod`](/reference/action-types/run/helm-pod)
  * [`exec`](/reference/action-types/run/exec)
* [Test](/reference/action-types/test)
  * [`container`](/reference/action-types/test/container)
  * [`kubernetes-exec`](/reference/action-types/test/kubernetes-exec)
  * [`kubernetes-pod`](/reference/action-types/test/kubernetes-pod)
  * [`helm-pod`](/reference/action-types/test/helm-pod)
  * [`exec`](/reference/action-types/test/exec)


# Build

* [`container`](/reference/action-types/build/container)
* [`jib-container`](/reference/action-types/build/jib-container)
* [`exec`](/reference/action-types/build/exec)


# container Build

## Description

Build a Docker container image, and (if applicable) push to a remote registry.

Below is the full schema reference for the action.

`container` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Build"        | Yes      |

### `allowPublish`

When false, disables publishing this build to remote registries via the publish command.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `buildAtSource`

By default, builds are *staged* in `.garden/build/<build name>` and that directory is used as the build context. This is done to avoid builds contaminating the source tree, which can end up confusing version computation, or a build including files that are not intended to be part of it. In most scenarios, the default behavior is desired and leads to the most predictable and verifiable builds, as well as avoiding potential confusion around file watching.

You *can* override this by setting `buildAtSource: true`, which basically sets the build root for this action at the location of the Build action config in the source tree. This means e.g. that the build command in `exec` Builds runs at the source, and for Docker image builds the build is initiated from the source directory.

An important implication is that `include` and `exclude` directives for the action, as well as `.gardenignore` files, only affect version hash computation but are otherwise not effective in controlling the build context. This may lead to unexpected variation in builds with the same version hash. **This may also slow down code synchronization to remote destinations, e.g. when performing remote Docker image builds.**

Additionally, any `exec` runtime actions (and potentially others) that reference this Build with the `build` field, will run from the source directory of this action.

While there may be good reasons to do this in some situations, please be aware that this increases the potential for side-effects and variability in builds. **You must take extra care**, including making sure that files generated during builds are excluded with e.g. `.gardenignore` files or `exclude` fields on potentially affected actions. Another potential issue is causing infinite loops when running with file-watching enabled, basically triggering a new build during the build.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `copyFrom[]`

Copy files from other builds, ahead of running this build.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `copyFrom[].build`

[copyFrom](#copyfrom) > build

The name of the Build action to copy from.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `copyFrom[].sourcePath`

[copyFrom](#copyfrom) > sourcePath

POSIX-style path or filename of the directory or file(s) to copy to the target, relative to the build path of the source build.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `copyFrom[].targetPath`

[copyFrom](#copyfrom) > targetPath

POSIX-style path or filename to copy the directory or file(s), relative to the build directory. Defaults to to same as source path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `include[]`

Specify a list of POSIX-style paths or globs that should be included as the build context for the Build, and will affect the computed *version* of the action.

If nothing is specified here, the whole directory may be assumed to be included in the build. Providers are sometimes able to infer the list of paths, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

You can *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the build context and the Build version.

Providers are sometimes able to infer the `include` field, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `timeout`

Set a timeout for the build to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `600`   | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localId`

[spec](#spec) > localId

Specify an image ID to use when building locally, instead of the default of using the action name. Must be a valid Docker image identifier. **Note that the image&#x20;*****tag*****&#x20;is always set to the action version.**

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.publishId`

[spec](#spec) > publishId

Specify an image ID to use when publishing the image (via the `garden publish` command), instead of the default of using the action name. Must be a valid Docker image identifier.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.targetStage`

[spec](#spec) > targetStage

For multi-stage Dockerfiles, specify which image/stage to build (see <https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target> for details).

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.buildArgs`

[spec](#spec) > buildArgs

Specify build arguments to use when building the container image.

Note: Garden will always set a `GARDEN_ACTION_VERSION` (alias `GARDEN_MODULE_VERSION`) argument with the module/build version at build time.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `spec.extraFlags[]`

[spec](#spec) > extraFlags

Specify extra flags to use when building the container image. Note that arguments may not be portable across implementations.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.platforms[]`

[spec](#spec) > platforms

Specify the platforms to build the image for. This is useful when building multi-platform images. The format is `os/arch`, e.g. `linux/amd64`, `linux/arm64`, etc.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.secrets`

[spec](#spec) > secrets

Secret values that can be mounted in the Dockerfile, but do not become part of the image filesystem or image manifest. This is useful e.g. for private registry auth tokens.

Build arguments and environment variables are inappropriate for secrets, as they persist in the final image.

The secret can later be consumed in the Dockerfile like so:

```
  RUN --mount=type=secret,id=mytoken TOKEN=$(cat /run/secrets/mytoken) ...
```

See also <https://docs.docker.com/build/building/secrets/>

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
spec:
  ...
  secrets:
      mytoken: supersecret
```

### `spec.dockerfile`

[spec](#spec) > dockerfile

POSIX-style name of a Dockerfile, relative to the action's source root.

| Type        | Default        | Required |
| ----------- | -------------- | -------- |
| `posixPath` | `"Dockerfile"` | No       |

## Outputs

The following keys are available via the `${actions.build.<name>}` template string key for `container` action.

### `${actions.build.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.build.my-build.disabled}
```

### `${actions.build.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.buildPath}
```

### `${actions.build.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.sourcePath}
```

### `${actions.build.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.build.my-build.mode}
```

### `${actions.build.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.build.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.build.<name>.outputs.localImageName}`

The name of the image (without tag/version) that the Build uses for local builds and deployments.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.outputs.localImageName}
```

### `${actions.build.<name>.outputs.localImageId}`

The full ID of the image (incl. tag/version) that the Build uses for local builds and deployments.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.outputs.localImageId}
```

### `${actions.build.<name>.outputs.deploymentImageName}`

The name of the image (without tag/version) that the Build will use during deployment.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.outputs.deploymentImageName}
```

### `${actions.build.<name>.outputs.deploymentImageId}`

The full ID of the image (incl. tag/version) that the Build will use during deployment.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.outputs.deploymentImageId}
```

### `${actions.build.<name>.outputs.deploymentImageTag}`

The version tag of the image that the Build will use during deployment.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.outputs.deploymentImageTag}
```

### `${actions.build.<name>.outputs.local-image-name}`

Alias for localImageName, for backward compatibility.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.outputs.local-image-id}`

Alias for localImageId, for backward compatibility.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.outputs.deployment-image-name}`

Alias for deploymentImageName, for backward compatibility.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.outputs.deployment-image-id}`

Alias for deploymentImageId, for backward compatibility.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.outputs.deployment-image-tag}`

Alias for deploymentImageTag, for backward compatibility.

| Type     |
| -------- |
| `string` |


# exec Build

## Description

A simple Build action which runs a build locally with a shell command.

Below is the full schema reference for the action.

`exec` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Build"        | Yes      |

### `allowPublish`

When false, disables publishing this build to remote registries via the publish command.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `buildAtSource`

By default, builds are *staged* in `.garden/build/<build name>` and that directory is used as the build context. This is done to avoid builds contaminating the source tree, which can end up confusing version computation, or a build including files that are not intended to be part of it. In most scenarios, the default behavior is desired and leads to the most predictable and verifiable builds, as well as avoiding potential confusion around file watching.

You *can* override this by setting `buildAtSource: true`, which basically sets the build root for this action at the location of the Build action config in the source tree. This means e.g. that the build command in `exec` Builds runs at the source, and for Docker image builds the build is initiated from the source directory.

An important implication is that `include` and `exclude` directives for the action, as well as `.gardenignore` files, only affect version hash computation but are otherwise not effective in controlling the build context. This may lead to unexpected variation in builds with the same version hash. **This may also slow down code synchronization to remote destinations, e.g. when performing remote Docker image builds.**

Additionally, any `exec` runtime actions (and potentially others) that reference this Build with the `build` field, will run from the source directory of this action.

While there may be good reasons to do this in some situations, please be aware that this increases the potential for side-effects and variability in builds. **You must take extra care**, including making sure that files generated during builds are excluded with e.g. `.gardenignore` files or `exclude` fields on potentially affected actions. Another potential issue is causing infinite loops when running with file-watching enabled, basically triggering a new build during the build.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `copyFrom[]`

Copy files from other builds, ahead of running this build.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `copyFrom[].build`

[copyFrom](#copyfrom) > build

The name of the Build action to copy from.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `copyFrom[].sourcePath`

[copyFrom](#copyfrom) > sourcePath

POSIX-style path or filename of the directory or file(s) to copy to the target, relative to the build path of the source build.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `copyFrom[].targetPath`

[copyFrom](#copyfrom) > targetPath

POSIX-style path or filename to copy the directory or file(s), relative to the build directory. Defaults to to same as source path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `include[]`

Specify a list of POSIX-style paths or globs that should be included as the build context for the Build, and will affect the computed *version* of the action.

If nothing is specified here, the whole directory may be assumed to be included in the build. Providers are sometimes able to infer the list of paths, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

You can *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the build context and the Build version.

Providers are sometimes able to infer the `include` field, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `timeout`

Set a timeout for the build to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `600`   | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.shell`

[spec](#spec) > shell

If `true`, runs file inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.

Note that if this is not set, no shell interpreter (Bash, `cmd.exe`, etc.) is used, so shell features such as variables substitution (`echo $PATH`) are not allowed.

We recommend against using this option since it is:

* not cross-platform, encouraging shell-specific syntax.
* slower, because of the additional shell interpretation.
* unsafe, potentially allowing command injection.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.command[]`

[spec](#spec) > command

The command to run to perform the build.

*Note: You may omit this if all you need is for other implicit actions to happen, like copying files from build dependencies etc.*

By default, the command is run inside the Garden build directory (under .garden/build/). If the top level `buildAtSource` directive is set to `true`, the command runs in the action source directory instead. Please see the docs for that field for more information and potential implications. Also note that other `exec` actions that reference this build via the `build` field will then also run from this action's source directory.

Example: `["npm","run","build"]`

| Type    | Default | Required |
| ------- | ------- | -------- |
| `array` | `[]`    | No       |

### `spec.statusCommand[]`

[spec](#spec) > statusCommand

The command to run to check the status of the action.

If this is specified, it is run before the action's `command`. If the status command runs successfully and returns exit code of 0, the action is considered already complete and the `command` is not run. To indicate that the action is not complete, the status command should return a non-zero exit code.

If this is not specified, the status is always reported as "unknown", so specifying this can be useful to avoid running the action unnecessarily.

Action outputs are also read from the directory after the status command is run (if the status is "ready"). If your action command writes outputs when run, you'll need to ensure that the outputs are consistent between the status command and the main command, to avoid unexpected results.

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `spec.env`

[spec](#spec) > env

Environment variables to set when running the command.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

## Outputs

The following keys are available via the `${actions.build.<name>}` template string key for `exec` action.

### `${actions.build.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.build.my-build.disabled}
```

### `${actions.build.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.buildPath}
```

### `${actions.build.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.sourcePath}
```

### `${actions.build.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.build.my-build.mode}
```

### `${actions.build.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.build.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.build.<name>.outputs.log}`

The full log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.build.<name>.outputs.stdout}`

The stdout log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.build.<name>.outputs.stderr}`

The stderr log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |


# jib-container Build

## Description

Extends the [container type](/reference/action-types/build/container) to build the image with [Jib](https://github.com/GoogleContainerTools/jib). Use this to efficiently build container images for Java services. Check out the [jib example](https://github.com/garden-io/garden/tree/0.14.20/examples/jib-container) to see it in action.

The image is always built locally, directly from the source directory (see the note on that below), before shipping the container image to the right place. You can set `build.tarOnly: true` to only build the image as a tarball.

By default (and when not using remote building), the image is pushed to the local Docker daemon, to match the behavior of and stay compatible with normal `container` actions.

When using remote building with the `kubernetes` provider, the image is synced to the cluster (where individual layers are cached) and then pushed to the deployment registry from there. This is to make sure any registry auth works seamlessly and exactly like for normal Docker image builds.

Please consult the [Jib documentation](https://github.com/GoogleContainerTools/jib) for how to configure Jib in your Gradle or Maven project.

To provide additional arguments to Gradle/Maven when building, you can set the `extraFlags` field.

**Important note:** Unlike many other types, `jib-container` builds are done from the *source* directory instead of the build staging directory, because of how Java projects are often laid out across a repository. This means build dependency copy directives are effectively ignored, and any include/exclude statements and .gardenignore files will not impact the build result. \_Note that you should still configure includes, excludes and/or a .gardenignore to tell Garden which files to consider as part of the Build version hash, to correctly detect whether a new build is required.\*\*

Below is the full schema reference for the action.

`jib-container` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Build"        | Yes      |

### `allowPublish`

When false, disables publishing this build to remote registries via the publish command.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `buildAtSource`

By default, builds are *staged* in `.garden/build/<build name>` and that directory is used as the build context. This is done to avoid builds contaminating the source tree, which can end up confusing version computation, or a build including files that are not intended to be part of it. In most scenarios, the default behavior is desired and leads to the most predictable and verifiable builds, as well as avoiding potential confusion around file watching.

You *can* override this by setting `buildAtSource: true`, which basically sets the build root for this action at the location of the Build action config in the source tree. This means e.g. that the build command in `exec` Builds runs at the source, and for Docker image builds the build is initiated from the source directory.

An important implication is that `include` and `exclude` directives for the action, as well as `.gardenignore` files, only affect version hash computation but are otherwise not effective in controlling the build context. This may lead to unexpected variation in builds with the same version hash. **This may also slow down code synchronization to remote destinations, e.g. when performing remote Docker image builds.**

Additionally, any `exec` runtime actions (and potentially others) that reference this Build with the `build` field, will run from the source directory of this action.

While there may be good reasons to do this in some situations, please be aware that this increases the potential for side-effects and variability in builds. **You must take extra care**, including making sure that files generated during builds are excluded with e.g. `.gardenignore` files or `exclude` fields on potentially affected actions. Another potential issue is causing infinite loops when running with file-watching enabled, basically triggering a new build during the build.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `copyFrom[]`

Copy files from other builds, ahead of running this build.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `copyFrom[].build`

[copyFrom](#copyfrom) > build

The name of the Build action to copy from.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `copyFrom[].sourcePath`

[copyFrom](#copyfrom) > sourcePath

POSIX-style path or filename of the directory or file(s) to copy to the target, relative to the build path of the source build.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `copyFrom[].targetPath`

[copyFrom](#copyfrom) > targetPath

POSIX-style path or filename to copy the directory or file(s), relative to the build directory. Defaults to to same as source path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `include[]`

Specify a list of POSIX-style paths or globs that should be included as the build context for the Build, and will affect the computed *version* of the action.

If nothing is specified here, the whole directory may be assumed to be included in the build. Providers are sometimes able to infer the list of paths, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

You can *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the build context and the Build version.

Providers are sometimes able to infer the `include` field, e.g. from a Dockerfile, but often this is inaccurate (say, if a Dockerfile has an `ADD .` statement) so it may be important to set `include` and/or `exclude` to define the build context. Otherwise you may find unrelated files being included in the build context and the build version, which may result in unnecessarily repeated builds.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `timeout`

Set a timeout for the build to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `600`   | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localId`

[spec](#spec) > localId

Specify an image ID to use when building locally, instead of the default of using the action name. Must be a valid Docker image identifier. **Note that the image&#x20;*****tag*****&#x20;is always set to the action version.**

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.publishId`

[spec](#spec) > publishId

Specify an image ID to use when publishing the image (via the `garden publish` command), instead of the default of using the action name. Must be a valid Docker image identifier.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.targetStage`

[spec](#spec) > targetStage

For multi-stage Dockerfiles, specify which image/stage to build (see <https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target> for details).

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.buildArgs`

[spec](#spec) > buildArgs

Specify build arguments to use when building the container image.

Note: Garden will always set a `GARDEN_ACTION_VERSION` (alias `GARDEN_MODULE_VERSION`) argument with the module/build version at build time.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `spec.platforms[]`

[spec](#spec) > platforms

Specify the platforms to build the image for. This is useful when building multi-platform images. The format is `os/arch`, e.g. `linux/amd64`, `linux/arm64`, etc.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.secrets`

[spec](#spec) > secrets

Secret values that can be mounted in the Dockerfile, but do not become part of the image filesystem or image manifest. This is useful e.g. for private registry auth tokens.

Build arguments and environment variables are inappropriate for secrets, as they persist in the final image.

The secret can later be consumed in the Dockerfile like so:

```
  RUN --mount=type=secret,id=mytoken TOKEN=$(cat /run/secrets/mytoken) ...
```

See also <https://docs.docker.com/build/building/secrets/>

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
spec:
  ...
  secrets:
      mytoken: supersecret
```

### `spec.dockerfile`

[spec](#spec) > dockerfile

POSIX-style name of a Dockerfile, relative to the action's source root.

| Type        | Default        | Required |
| ----------- | -------------- | -------- |
| `posixPath` | `"Dockerfile"` | No       |

### `spec.projectType`

[spec](#spec) > projectType

The type of project to build. Defaults to auto-detecting between gradle and maven (based on which files/directories are found in the action root), but in some cases you may need to specify it.

| Type     | Allowed Values                             | Default  | Required |
| -------- | ------------------------------------------ | -------- | -------- |
| `string` | "gradle", "maven", "jib", "auto", "mavend" | `"auto"` | Yes      |

### `spec.jdkVersion`

[spec](#spec) > jdkVersion

The JDK version to use.

The chosen version will be downloaded by Garden and used to define `JAVA_HOME` environment variable for Gradle and Maven.

To use an arbitrary JDK distribution, please use the `jdkPath` configuration option.

| Type     | Allowed Values        | Default | Required |
| -------- | --------------------- | ------- | -------- |
| `number` | 8, 11, 13, 17, 21, 23 | `11`    | Yes      |

### `spec.jdkPath`

[spec](#spec) > jdkPath

The JDK home path. This **always overrides** the JDK defined in `jdkVersion`.

The value will be used as `JAVA_HOME` environment variable for Gradle and Maven.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
spec:
  ...
  jdkPath: "${local.env.JAVA_HOME}"
```

### `spec.dockerBuild`

[spec](#spec) > dockerBuild

Build the image and push to a local Docker daemon (i.e. use the `jib:dockerBuild` / `jibDockerBuild` target).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.tarOnly`

[spec](#spec) > tarOnly

Don't load or push the resulting image to a Docker daemon or registry, only build it as a tar file.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.tarFormat`

[spec](#spec) > tarFormat

Specify the image format in the resulting tar file. Only used if `tarOnly: true`.

| Type     | Allowed Values  | Default    | Required |
| -------- | --------------- | ---------- | -------- |
| `string` | "docker", "oci" | `"docker"` | Yes      |

### `spec.gradlePath`

[spec](#spec) > gradlePath

Defines the location of the custom executable Gradle binary.

If not provided, then the Gradle binary available in the working directory will be used. If no Gradle binary found in the working dir, then Gradle 7.6.4 will be downloaded and used.

**Note!** Either `jdkVersion` or `jdkPath` will be used to define `JAVA_HOME` environment variable for the custom Gradle. To ensure a system JDK usage, please set `jdkPath` to `${local.env.JAVA_HOME}`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.mavenPath`

[spec](#spec) > mavenPath

Defines the location of the custom executable Maven binary.

If not provided, then Maven 3.9.9 will be downloaded and used.

**Note!** Either `jdkVersion` or `jdkPath` will be used to define `JAVA_HOME` environment variable for the custom Maven. To ensure a system JDK usage, please set `jdkPath` to `${local.env.JAVA_HOME}`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.mavenPhases[]`

[spec](#spec) > mavenPhases

Defines the Maven phases to be executed during the Garden build step.

| Type            | Default       | Required |
| --------------- | ------------- | -------- |
| `array[string]` | `["compile"]` | No       |

### `spec.mavendPath`

[spec](#spec) > mavendPath

Defines the location of the custom executable Maven Daemon binary.

If not provided, then Maven Daemon 1.0.2 will be downloaded and used.

**Note!** Either `jdkVersion` or `jdkPath` will be used to define `JAVA_HOME` environment variable for the custom Maven Daemon. To ensure a system JDK usage, please set `jdkPath` to `${local.env.JAVA_HOME}`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.concurrentMavenBuilds`

[spec](#spec) > concurrentMavenBuilds

{% hint style="warning" %}
**Experimental**: this is an experimental feature and the API might change in the future.
{% endhint %}

\[EXPERIMENTAL] Enable/disable concurrent Maven and Maven Daemon builds.

Note! Concurrent builds can be unstable. This option is disabled by default. This option must be configured for each Build action individually.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.extraFlags[]`

[spec](#spec) > extraFlags

Specify extra flags to pass to maven/gradle when building the container image.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

## Outputs

The following keys are available via the `${actions.build.<name>}` template string key for `jib-container` action.

### `${actions.build.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.build.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.build.my-build.disabled}
```

### `${actions.build.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.buildPath}
```

### `${actions.build.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.build.my-build.sourcePath}
```

### `${actions.build.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.build.my-build.mode}
```

### `${actions.build.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.build.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |


# Deploy

* [`container`](/reference/action-types/deploy/container)
* [`kubernetes`](/reference/action-types/deploy/kubernetes)
* [`helm`](/reference/action-types/deploy/helm)
* [`exec`](/reference/action-types/deploy/exec)
* [`terraform`](/reference/action-types/deploy/terraform)
* [`pulumi`](/reference/action-types/deploy/pulumi)


# container Deploy

## Description

Deploy a container image, e.g. in a Kubernetes namespace (when used with the `kubernetes` provider).

This is a simplified abstraction, which can be convenient for simple deployments, but has limited features compared to more platform-specific types. For example, you cannot specify replicas for redundancy, and various platform-specific options are not included. For more flexibility, please look at other Deploy types like [helm](/reference/action-types/deploy/helm) or [kubernetes](/reference/action-types/deploy/kubernetes).

Below is the full schema reference for the action.

`container` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.command[]`

[spec](#spec) > command

The command/entrypoint to run the container with.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
spec:
  ...
  command:
    - /bin/sh
    - '-c'
```

### `spec.args[]`

[spec](#spec) > args

The arguments (on top of the `command`, i.e. entrypoint) to run the container with.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
spec:
  ...
  args:
    - npm
    - start
```

### `spec.env`

[spec](#spec) > env

Key/value map of environment variables. Keys must be valid POSIX environment variable names (must not start with `GARDEN`) and values must be primitives or references to secrets.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
spec:
  ...
  env:
      - MY_VAR: some-value
        MY_SECRET_VAR:
          secretRef:
            name: my-secret
            key: some-key
      - {}
```

### `spec.cpu`

[spec](#spec) > cpu

| Type     | Default                 | Required |
| -------- | ----------------------- | -------- |
| `object` | `{"min":10,"max":1000}` | No       |

### `spec.cpu.min`

[spec](#spec) > [cpu](#speccpu) > min

The minimum amount of CPU the container needs to be available for it to be deployed, in millicpus (i.e. 1000 = 1 CPU)

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `10`    | No       |

### `spec.cpu.max`

[spec](#spec) > [cpu](#speccpu) > max

The maximum amount of CPU the container can use, in millicpus (i.e. 1000 = 1 CPU). If set to null will result in no limit being set.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `1000`  | No       |

### `spec.memory`

[spec](#spec) > memory

| Type     | Default                 | Required |
| -------- | ----------------------- | -------- |
| `object` | `{"min":90,"max":1024}` | No       |

### `spec.memory.min`

[spec](#spec) > [memory](#specmemory) > min

The minimum amount of RAM the container needs to be available for it to be deployed, in megabytes (i.e. 1024 = 1 GB)

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `90`    | No       |

### `spec.memory.max`

[spec](#spec) > [memory](#specmemory) > max

The maximum amount of RAM the container can use, in megabytes (i.e. 1024 = 1 GB) If set to null will result in no limit being set.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `1024`  | No       |

### `spec.volumes[]`

[spec](#spec) > volumes

List of volumes that should be mounted when starting the container.

Note: If neither `hostPath` nor `action` is specified, an empty ephemeral volume is created and mounted when deploying the container.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.volumes[].name`

[spec](#spec) > [volumes](#specvolumes) > name

The name of the allocated volume.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.volumes[].containerPath`

[spec](#spec) > [volumes](#specvolumes) > containerPath

The path where the volume should be mounted in the container.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `spec.volumes[].hostPath`

[spec](#spec) > [volumes](#specvolumes) > hostPath

*NOTE: Usage of hostPath is generally discouraged, since it doesn't work reliably across different platforms and providers. Some providers may not support it at all.*

A local path or path on the node that's running the container, to mount in the container, relative to the config source directory (or absolute).

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

Example:

```yaml
spec:
  ...
  volumes:
    - hostPath: "/some/dir"
```

### `spec.privileged`

[spec](#spec) > privileged

If true, run the main container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.addCapabilities[]`

[spec](#spec) > addCapabilities

POSIX capabilities to add when running the container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.dropCapabilities[]`

[spec](#spec) > dropCapabilities

POSIX capabilities to remove when running the container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.tty`

[spec](#spec) > tty

Specify if containers in this action have TTY support enabled (which implies having stdin support enabled).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.deploymentStrategy`

[spec](#spec) > deploymentStrategy

Specifies the container's deployment strategy.

| Type     | Allowed Values              | Default           | Required |
| -------- | --------------------------- | ----------------- | -------- |
| `string` | "RollingUpdate", "Recreate" | `"RollingUpdate"` | Yes      |

### `spec.annotations`

[spec](#spec) > annotations

Annotations to attach to the service *(note: May not be applicable to all providers)*.

When using the Kubernetes provider, these annotations are applied to both Service and Pod resources. You can generally specify the annotations intended for both Pods or Services here, and the ones that don't apply on either side will be ignored (i.e. if you put a Service annotation here, it'll also appear on Pod specs but will be safely ignored there, and vice versa).

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
spec:
  ...
  annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: '0'
```

### `spec.daemon`

[spec](#spec) > daemon

Whether to run the service as a daemon (to ensure exactly one instance runs per node). May not be supported by all providers.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.sync`

[spec](#spec) > sync

Specifies which files or directories to sync to which paths inside the running containers of the service when it's in sync mode, and overrides for the container command and/or arguments.

Sync is enabled e.g. by setting the `--sync` flag on the `garden deploy` command.

See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for more information.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.args[]`

[spec](#spec) > [sync](#specsync) > args

Override the default container arguments when in sync mode.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.command[]`

[spec](#spec) > [sync](#specsync) > command

Override the default container command (i.e. entrypoint) when in sync mode.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.paths[]`

[spec](#spec) > [sync](#specsync) > paths

Specify one or more source files or directories to automatically sync with the running container.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.sync.paths[].source`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > source

Path to a local directory to be synchronized with the target. This should generally be a templated path to another action's source path (e.g. `${actions.build.my-container-image.sourcePath}`), or a relative path. If a path is hard-coded, we recommend sticking with relative paths here, and using forward slashes (`/`) as a delimiter, as Windows-style paths with back slashes (`\`) and absolute paths will work on some platforms, but they are not portable and will not work for users on other platforms. Defaults to the Deploy action's config's directory if no value is provided.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"."`   | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - source: "src"
```

### `spec.sync.paths[].target`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > target

POSIX-style absolute path to sync to inside the container. The root path (i.e. "/") is not allowed.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - target: "/app/src"
```

### `spec.sync.paths[].exclude[]`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - exclude:
          - dist/**/*
          - '*.log'
```

### `spec.sync.paths[].mode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > mode

The sync mode to use for the given paths. See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for details.

| Type     | Allowed Values                                                                                                                            | Default          | Required |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- |
| `string` | "one-way", "one-way-safe", "one-way-replica", "one-way-reverse", "one-way-replica-reverse", "two-way", "two-way-safe", "two-way-resolved" | `"one-way-safe"` | Yes      |

### `spec.sync.paths[].defaultFileMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultFileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `spec.sync.paths[].defaultDirectoryMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultDirectoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `spec.sync.paths[].defaultOwner`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultOwner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.paths[].defaultGroup`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultGroup

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.image`

[spec](#spec) > image

Specify an image ID to deploy. Should be a valid Docker image identifier. Required.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.ingresses[]`

[spec](#spec) > ingresses

List of ingress endpoints that the service exposes.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

Example:

```yaml
spec:
  ...
  ingresses:
    - path: /api
      port: http
```

### `spec.ingresses[].annotations`

[spec](#spec) > [ingresses](#specingresses) > annotations

Annotations to attach to the ingress (Note: May not be applicable to all providers)

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
spec:
  ...
  ingresses:
    - path: /api
      port: http
    - annotations:
          nginx.ingress.kubernetes.io/proxy-body-size: '0'
```

### `spec.ingresses[].hostname`

[spec](#spec) > [ingresses](#specingresses) > hostname

The hostname that should route to this service. Defaults to the default hostname configured in the provider configuration.

Note that if you're developing locally you may need to add this hostname to your hosts file.

| Type       | Required |
| ---------- | -------- |
| `hostname` | No       |

### `spec.ingresses[].linkUrl`

[spec](#spec) > [ingresses](#specingresses) > linkUrl

The link URL for the ingress to show in the console and in dashboards. Also used when calling the service with the `call` command.

Use this if the actual URL is different from what's specified in the ingress, e.g. because there's a load balancer in front of the service that rewrites the paths.

Otherwise Garden will construct the link URL from the ingress spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.ingresses[].path`

[spec](#spec) > [ingresses](#specingresses) > path

The path which should be routed to the service.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"/"`   | No       |

### `spec.ingresses[].port`

[spec](#spec) > [ingresses](#specingresses) > port

The name of the container port where the specified paths should be routed.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.healthCheck`

[spec](#spec) > healthCheck

Specify how the service's health should be checked after deploying.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.healthCheck.httpGet`

[spec](#spec) > [healthCheck](#spechealthcheck) > httpGet

Set this to check the service's health by making an HTTP request.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.healthCheck.httpGet.path`

[spec](#spec) > [healthCheck](#spechealthcheck) > [httpGet](#spechealthcheckhttpget) > path

The path of the service's health check endpoint.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.healthCheck.httpGet.port`

[spec](#spec) > [healthCheck](#spechealthcheck) > [httpGet](#spechealthcheckhttpget) > port

The name of the port where the service's health check endpoint should be available.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.healthCheck.httpGet.scheme`

[spec](#spec) > [healthCheck](#spechealthcheck) > [httpGet](#spechealthcheckhttpget) > scheme

| Type     | Default  | Required |
| -------- | -------- | -------- |
| `string` | `"HTTP"` | No       |

### `spec.healthCheck.command[]`

[spec](#spec) > [healthCheck](#spechealthcheck) > command

Set this to check the service's health by running a command in its container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.healthCheck.tcpPort`

[spec](#spec) > [healthCheck](#spechealthcheck) > tcpPort

Set this to check the service's health by checking if this TCP port is accepting connections.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.healthCheck.readinessTimeoutSeconds`

[spec](#spec) > [healthCheck](#spechealthcheck) > readinessTimeoutSeconds

The maximum number of seconds to wait until the readiness check counts as failed.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `3`     | No       |

### `spec.healthCheck.livenessTimeoutSeconds`

[spec](#spec) > [healthCheck](#spechealthcheck) > livenessTimeoutSeconds

The maximum number of seconds to wait until the liveness check counts as failed.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `3`     | No       |

### `spec.timeout`

[spec](#spec) > timeout

The maximum duration (in seconds) to wait for resources to deploy and become healthy.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `spec.limits`

[spec](#spec) > limits

{% hint style="warning" %}
**Deprecated**: Please use the `cpu` and `memory` configuration fields instead.
{% endhint %}

Specify resource limits for the service.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.limits.cpu`

[spec](#spec) > [limits](#speclimits) > cpu

{% hint style="warning" %}
**Deprecated**: This field will be removed in a future release.
{% endhint %}

The maximum amount of CPU the service can use, in millicpus (i.e. 1000 = 1 CPU)

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.limits.memory`

[spec](#spec) > [limits](#speclimits) > memory

{% hint style="warning" %}
**Deprecated**: This field will be removed in a future release.
{% endhint %}

The maximum amount of RAM the service can use, in megabytes (i.e. 1024 = 1 GB)

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.ports[]`

[spec](#spec) > ports

List of ports that the service container exposes.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.ports[].name`

[spec](#spec) > [ports](#specports) > name

The name of the port (used when referencing the port elsewhere in the service configuration).

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.ports[].protocol`

[spec](#spec) > [ports](#specports) > protocol

The protocol of the port.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"TCP"` | No       |

### `spec.ports[].containerPort`

[spec](#spec) > [ports](#specports) > containerPort

The port exposed on the container by the running process. This will also be the default value for `servicePort`. This is the port you would expose in your Dockerfile and that your process listens on. This is commonly a non-privileged port like 8080 for security reasons. The service port maps to the container port: `servicePort:80 -> containerPort:8080 -> process:8080`

| Type     | Required |
| -------- | -------- |
| `number` | Yes      |

Example:

```yaml
spec:
  ...
  ports:
    - containerPort: 8080
```

### `spec.ports[].localPort`

[spec](#spec) > [ports](#specports) > localPort

Specify a preferred local port to attach to when creating a port-forward to the service port. If this port is busy, a warning will be shown and an alternative port chosen.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
spec:
  ...
  ports:
    - localPort: 10080
```

### `spec.ports[].servicePort`

[spec](#spec) > [ports](#specports) > servicePort

The port exposed on the service. Defaults to `containerPort` if not specified. This is the port you use when calling a service from another service within the cluster. For example, if your service name is my-service and the service port is 8090, you would call it with: <http://my-service:8090/some-endpoint>. It is common to use port 80, the default port number, so that you can call the service directly with <http://my-service/some-endpoint>. The service port maps to the container port: `servicePort:80 -> containerPort:8080 -> process:8080`

| Type     | Required |
| -------- | -------- |
| `number` | No       |

Example:

```yaml
spec:
  ...
  ports:
    - servicePort: 80
```

### `spec.ports[].hostPort`

[spec](#spec) > [ports](#specports) > hostPort

{% hint style="warning" %}
**Deprecated**: It's generally not recommended to use the `hostPort` field of the `V1ContainerPort` spec. You can learn more about Kubernetes best practices at: <https://kubernetes.io/docs/concepts/configuration/overview/>
{% endhint %}

Number of port to expose on the pod's IP address.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.ports[].nodePort`

[spec](#spec) > [ports](#specports) > nodePort

Set this to expose the service on the specified port on the host node (may not be supported by all providers). Set to `true` to have the cluster pick a port automatically, which is most often advisable if the cluster is shared by multiple users. This allows you to call the service from the outside by the node's IP address and the port number set in this field.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.replicas`

[spec](#spec) > replicas

The number of instances of the service to deploy. Defaults to 3 for environments configured with `production: true`, otherwise 1. Note: This setting may be overridden or ignored in some cases. For example, when running with `daemon: true` or if the provider doesn't support multiple replicas.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `container` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.deploy.<name>.outputs.deployedImageId}`

The ID of the image that was deployed.

| Type     |
| -------- |
| `string` |


# exec Deploy

## Description

Run and manage a persistent process or service with shell commands.

Below is the full schema reference for the action.

`exec` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.shell`

[spec](#spec) > shell

If `true`, runs file inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.

Note that if this is not set, no shell interpreter (Bash, `cmd.exe`, etc.) is used, so shell features such as variables substitution (`echo $PATH`) are not allowed.

We recommend against using this option since it is:

* not cross-platform, encouraging shell-specific syntax.
* slower, because of the additional shell interpretation.
* unsafe, potentially allowing command injection.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.persistent`

[spec](#spec) > persistent

Set this to true if the `deployCommand` is not expected to return, and should run until the Garden command is manually terminated.

This replaces the previously supported `devMode` from `exec` actions.

If this is set to true, it is highly recommended to also define `statusCommand` if possible. Otherwise the Deploy is considered to be immediately ready once the `deployCommand` is started.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.deployCommand[]`

[spec](#spec) > deployCommand

The command to run to perform the deployment.

**Action outputs**

Exec actions can write outputs to a JSON file or a directory. The action command is provided with the path to the outputs directory or JSON file via the `GARDEN_ACTION_OUTPUTS_PATH` or `GARDEN_ACTION_OUTPUTS_JSON_PATH` environment variables.

If you write a JSON file to `<GARDEN_ACTION_OUTPUTS_JSON_PATH>` this file will be read and its contents will be used as the action outputs. Nested JSON objects are not supported. Only the top-level key-value pairs, where values are primitive types (string, number, boolean, null), will be used.

You can also write outputs to files in the directory. In this scenario, each file with a valid identifier as a filename (this excludes paths starting with `.` for example) in the directory will be read and its filename will be added as the key in the action outputs, with the contents of the file as the value. Sub-directories are not supported and will be ignored. For example, if you write some string to `<GARDEN_ACTION_OUTPUTS_PATH>/my-output`, the action outputs will contain a `my-output` key with the value `<contents of my-output.txt>`.

It is allowed to mix and match between the two approaches. In that scenario the JSON file will be read first, and any additional valid filenames in the directory will be added as additional action outputs, overriding keys in the JSON file if they overlap.

Note that if you provide a `statusCommand`, the outputs will also be read from the directory after the status command is run. You'll need to ensure that the outputs are consistent between the status command and the command that is run, to avoid unexpected results.

**Build field**

Note that if a Build is referenced in the `build` field, the command will be run from the build directory for that Build action. If that Build has `buildAtSource: true` set, the command will be run from the source directory of the Build action. If no `build` reference is set, the command is run from the source directory of this action.

| Type    | Required |
| ------- | -------- |
| `array` | Yes      |

### `spec.statusCommand[]`

[spec](#spec) > statusCommand

Optionally set a command to check the status of the deployment. If this is specified, it is run before the `deployCommand`. If the command runs successfully and returns exit code of 0, the deployment is considered already deployed and the `deployCommand` is not run.

If this is not specified, the deployment is always reported as "unknown", so it's highly recommended to specify this command if possible.

If `persistent: true`, Garden will run this command at an interval until it returns a zero exit code or times out.

**Action outputs**

Exec actions can write outputs to a JSON file or a directory. The action command is provided with the path to the outputs directory or JSON file via the `GARDEN_ACTION_OUTPUTS_PATH` or `GARDEN_ACTION_OUTPUTS_JSON_PATH` environment variables.

If you write a JSON file to `<GARDEN_ACTION_OUTPUTS_JSON_PATH>` this file will be read and its contents will be used as the action outputs. Nested JSON objects are not supported. Only the top-level key-value pairs, where values are primitive types (string, number, boolean, null), will be used.

You can also write outputs to files in the directory. In this scenario, each file with a valid identifier as a filename (this excludes paths starting with `.` for example) in the directory will be read and its filename will be added as the key in the action outputs, with the contents of the file as the value. Sub-directories are not supported and will be ignored. For example, if you write some string to `<GARDEN_ACTION_OUTPUTS_PATH>/my-output`, the action outputs will contain a `my-output` key with the value `<contents of my-output.txt>`.

It is allowed to mix and match between the two approaches. In that scenario the JSON file will be read first, and any additional valid filenames in the directory will be added as additional action outputs, overriding keys in the JSON file if they overlap.

Note that if you provide a `statusCommand`, the outputs will also be read from the directory after the status command is run. You'll need to ensure that the outputs are consistent between the status command and the command that is run, to avoid unexpected results.

**Build field**

Note that if a Build is referenced in the `build` field, the command will be run from the build directory for that Build action. If that Build has `buildAtSource: true` set, the command will be run from the source directory of the Build action. If no `build` reference is set, the command is run from the source directory of this action.

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `spec.cleanupCommand[]`

[spec](#spec) > cleanupCommand

Optionally set a command to clean the deployment up, e.g. when running `garden delete env`.

**Action outputs**

Exec actions can write outputs to a JSON file or a directory. The action command is provided with the path to the outputs directory or JSON file via the `GARDEN_ACTION_OUTPUTS_PATH` or `GARDEN_ACTION_OUTPUTS_JSON_PATH` environment variables.

If you write a JSON file to `<GARDEN_ACTION_OUTPUTS_JSON_PATH>` this file will be read and its contents will be used as the action outputs. Nested JSON objects are not supported. Only the top-level key-value pairs, where values are primitive types (string, number, boolean, null), will be used.

You can also write outputs to files in the directory. In this scenario, each file with a valid identifier as a filename (this excludes paths starting with `.` for example) in the directory will be read and its filename will be added as the key in the action outputs, with the contents of the file as the value. Sub-directories are not supported and will be ignored. For example, if you write some string to `<GARDEN_ACTION_OUTPUTS_PATH>/my-output`, the action outputs will contain a `my-output` key with the value `<contents of my-output.txt>`.

It is allowed to mix and match between the two approaches. In that scenario the JSON file will be read first, and any additional valid filenames in the directory will be added as additional action outputs, overriding keys in the JSON file if they overlap.

Note that if you provide a `statusCommand`, the outputs will also be read from the directory after the status command is run. You'll need to ensure that the outputs are consistent between the status command and the command that is run, to avoid unexpected results.

**Build field**

Note that if a Build is referenced in the `build` field, the command will be run from the build directory for that Build action. If that Build has `buildAtSource: true` set, the command will be run from the source directory of the Build action. If no `build` reference is set, the command is run from the source directory of this action.

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `spec.statusTimeout`

[spec](#spec) > statusTimeout

The maximum duration (in seconds) to wait for a for the `statusCommand` to return a zero exit code. Ignored if no `statusCommand` is set.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `10`    | No       |

### `spec.env`

[spec](#spec) > env

Environment variables to set when running the deploy and status commands.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `exec` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.deploy.<name>.outputs.log}`

The full log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.deploy.<name>.outputs.stdout}`

The stdout log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.deploy.<name>.outputs.stderr}`

The stderr log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |


# helm Deploy

## Description

Specify a Helm chart (either in your repository or remote from a registry) to deploy.

Refer to the [Helm guide](/using-garden-with/kubernetes/install-helm-chart) for usage instructions.

Garden uses Helm 3.18.3.

Below is the full schema reference for the action.

`helm` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.namespace`

[spec](#spec) > namespace

A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63 characters.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.portForwards[]`

[spec](#spec) > portForwards

Manually specify port forwards that Garden should set up when deploying in dev or watch mode. If specified, these override the auto-detection of forwardable ports, so you'll need to specify the full list of port forwards to create.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.portForwards[].name`

[spec](#spec) > [portForwards](#specportforwards) > name

An identifier to describe the port forward.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.portForwards[].resource`

[spec](#spec) > [portForwards](#specportforwards) > resource

The full resource kind and name to forward to, e.g. Service/my-service or Deployment/my-deployment. Note that Garden will not validate this ahead of attempting to start the port forward, so you need to make sure this is correctly set. The types of resources supported will match that of the `kubectl port-forward` CLI command.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.portForwards[].targetPort`

[spec](#spec) > [portForwards](#specportforwards) > targetPort

The port number on the remote resource to forward to.

| Type     | Required |
| -------- | -------- |
| `number` | Yes      |

### `spec.portForwards[].localPort`

[spec](#spec) > [portForwards](#specportforwards) > localPort

The *preferred* local port to forward from. If none is set, a random port is chosen. If the specified port is not available, a warning is shown and a random port chosen instead.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.releaseName`

[spec](#spec) > releaseName

Optionally override the release name used when installing (defaults to the Deploy name).

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.timeout`

[spec](#spec) > timeout

Time in seconds to wait for Helm to complete any individual Kubernetes operation (like Jobs for hooks).

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `spec.values`

[spec](#spec) > values

Map of values to pass to Helm when rendering the templates. May include arrays and nested objects. When specified, these take precedence over the values in the `values.yaml` file (or the files specified in `valueFiles`).

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `spec.valueFiles[]`

[spec](#spec) > valueFiles

Specify value files to use when rendering the Helm chart. These will take precedence over the `values.yaml` file bundled in the Helm chart, and should be specified in ascending order of precedence. Meaning, the last file in this list will have the highest precedence.

If you *also* specify keys under the `values` field, those will effectively be added as another file at the end of this list, so they will take precedence over other files listed here.

Note that the paths here should be relative to the *config* root, and the files should be contained in this action config's directory.

| Type               | Default | Required |
| ------------------ | ------- | -------- |
| `array[posixPath]` | `[]`    | No       |

### `spec.atomic`

[spec](#spec) > atomic

Whether to set the `--atomic` flag during installs and upgrades. Set to `true` if you'd like the changes applied to be reverted on failure. Set to false if e.g. you want to see more information about failures and then manually roll back, instead of having Helm do it automatically on failure.

Note that setting `atomic` to `true` implies `wait`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.waitForUnhealthyResources`

[spec](#spec) > waitForUnhealthyResources

Whether to wait for the Helm command to complete before throwing an error if one of the resources being installed/upgraded is unhealthy.

By default, Garden will monitor the resources being created by Helm and throw an error as soon as one of them is unhealthy. This allows Garden to fail fast if there's an issue with one of the resources. If no issue is detected, Garden waits for the Helm command to complete.

If however `waitForUnhealthyResources` is set to `true` and some resources are unhealthy, then Garden will wait for Helm itself to throw an error which typically happens when it times out in the case of unhealthy resources (e.g. due to `ImagePullBackOff` or `CrashLoopBackOff` errors).

Waiting for the timeout can take awhile so using the default value here is recommended unless you'd like to completely mimic Helm's behaviour and not rely on Garden's resource monitoring.

Note that setting `atomic` to `true` implies `waitForUnhealthyResources`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.chart`

[spec](#spec) > chart

Specify the Helm chart to use.

If the chart is defined in the same directory as the action, you can skip this, and the chart sources will be detected. If the chart is in the source tree but in a sub-directory, you should set `chart.path` to the directory path, relative to the action directory.

For remote charts, there are multiple options:

* [**Helm Chart repository**](https://helm.sh/docs/topics/chart_repository/): specify `chart.name` and `chart.version\, and optionally` chart.repo\` (if the chart is not in the default "stable" repo).
* [**OCI-Based Registry**](https://helm.sh/docs/topics/registries/): specify `chart.url` with the `oci://` URL and optionally `chart.version`.
* **Absolute URL to a packaged chart**: specify `chart.url`.

One of `chart.name`, `chart.path` or `chart.url` must be specified.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.chart.name`

[spec](#spec) > [chart](#specchart) > name

A valid Helm chart name or URI (same as you'd input to `helm install`) Required if the action doesn't contain the Helm chart itself.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

Example:

```yaml
spec:
  ...
  chart:
    ...
    name: "ingress-nginx"
```

### `spec.chart.path`

[spec](#spec) > [chart](#specchart) > path

The path, relative to the action path, to the chart sources (i.e. where the Chart.yaml file is, if any).

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `spec.chart.repo`

[spec](#spec) > [chart](#specchart) > repo

The repository URL to fetch the chart from. Defaults to the "stable" helm repo (<https://charts.helm.sh/stable>).

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.chart.url`

[spec](#spec) > [chart](#specchart) > url

URL to OCI repository, or a URL to a packaged Helm chart archive.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.chart.version`

[spec](#spec) > [chart](#specchart) > version

The chart version to deploy.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.defaultTarget`

[spec](#spec) > defaultTarget

Specify a default resource in the deployment to use for syncs and for the `garden exec` command.

Specify either `kind` and `name`, or a `podSelector`. The resource should be one of the resources deployed by this action (otherwise the target is not guaranteed to be deployed with adjustments required for syncing).

Set `containerName` to specify a container to connect to in the remote Pod. By default the first container in the Pod is used.

Note that if you specify `podSelector` here, it is not validated to be a selector matching one of the resources deployed by the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.defaultTarget.kind`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.defaultTarget.name`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.defaultTarget.podSelector`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.defaultTarget.containerName`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync`

[spec](#spec) > sync

Configure path syncs for the resources in this Deploy.

If you have multiple syncs for the Deploy, you can use the `defaults` field to set common configuration for every individual sync.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.defaults`

[spec](#spec) > [sync](#specsync) > defaults

Defaults to set across every sync for this Deploy. If you use the `exclude` field here, it will be merged with any excludes set in individual syncs. These are applied on top of any defaults set in the provider configuration.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.defaults.exclude[]`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    defaults:
      ...
      exclude:
        - dist/**/*
        - '*.log'
```

### `spec.sync.defaults.fileMode`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > fileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `spec.sync.defaults.directoryMode`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > directoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `spec.sync.defaults.owner`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > owner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.defaults.group`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > group

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.paths[]`

[spec](#spec) > [sync](#specsync) > paths

A list of syncs to start once the Deploy is successfully started.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.sync.paths[].target`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > target

The Kubernetes resource to sync to. If specified, this is used instead of `spec.defaultTarget`.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.paths[].target.kind`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.sync.paths[].target.name`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.paths[].target.podSelector`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.paths[].target.containerName`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.paths[].sourcePath`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > sourcePath

Path to a local directory to be synchronized with the target. This should generally be a templated path to another action's source path (e.g. `${actions.build.my-container-image.sourcePath}`), or a relative path. If a path is hard-coded, we recommend sticking with relative paths here, and using forward slashes (`/`) as a delimiter, as Windows-style paths with back slashes (`\`) and absolute paths will work on some platforms, but they are not portable and will not work for users on other platforms. Defaults to the Deploy action's config's directory if no value is provided.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"."`   | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - sourcePath: "src"
```

### `spec.sync.paths[].containerPath`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > containerPath

POSIX-style absolute path to sync to inside the container. The root path (i.e. "/") is not allowed.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - containerPath: "/app/src"
```

### `spec.sync.paths[].exclude[]`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - exclude:
          - dist/**/*
          - '*.log'
```

### `spec.sync.paths[].mode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > mode

The sync mode to use for the given paths. See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for details.

| Type     | Allowed Values                                                                                                                            | Default          | Required |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- |
| `string` | "one-way", "one-way-safe", "one-way-replica", "one-way-reverse", "one-way-replica-reverse", "two-way", "two-way-safe", "two-way-resolved" | `"one-way-safe"` | Yes      |

### `spec.sync.paths[].defaultFileMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultFileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `spec.sync.paths[].defaultDirectoryMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultDirectoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `spec.sync.paths[].defaultOwner`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultOwner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.paths[].defaultGroup`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultGroup

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.overrides[]`

[spec](#spec) > [sync](#specsync) > overrides

Overrides for the container command and/or arguments for when in sync mode.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.sync.overrides[].target`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > target

The Kubernetes resources to override. If specified, this is used instead of `spec.defaultTarget`.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.overrides[].target.kind`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.sync.overrides[].target.name`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.overrides[].target.podSelector`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.overrides[].target.containerName`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.overrides[].command[]`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > command

Override the command/entrypoint in the matched container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.overrides[].args[]`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > args

Override the args in the matched container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.overrides[].image`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > image

Override the image of the matched container.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.localVolumes`

[spec](#spec) > localVolumes

**Experimental**: Configure local host volume mounts for development. When enabled, Garden injects hostPath volumes into the target workloads, mapping local directories into containers. This is useful for local development where you want to mount source code directly instead of using file sync.

Garden automatically converts host paths to the correct format based on the local Kubernetes cluster type (Docker Desktop, kind, minikube, Orbstack) and OS (macOS, Linux, Windows).

Note: This feature is still experimental and its configuration format may change in future releases.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localVolumes.enabled`

[spec](#spec) > [localVolumes](#speclocalvolumes) > enabled

Whether local volume mounts are enabled for this action. Defaults to true when volumes are defined.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.localVolumes.volumes[]`

[spec](#spec) > [localVolumes](#speclocalvolumes) > volumes

List of local volumes to mount into the target resource(s). Each volume maps a host directory to a container path in the specified target workload.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.localVolumes.volumes[].name`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > name

A unique name for this volume mount.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > target

The target resource to mount this volume into. Overrides `spec.defaultTarget` if set.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localVolumes.volumes[].target.kind`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > kind

The kind of the target resource (e.g. Deployment, StatefulSet).

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target.name`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > name

The name of the target resource.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target.containerName`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > containerName

The name of the container to mount the volume into. Defaults to the first container.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.localVolumes.volumes[].sourcePath`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > sourcePath

The path on the host, relative to the action source directory, to mount into the container.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `spec.localVolumes.volumes[].containerPath`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > containerPath

The absolute path inside the container where the volume should be mounted.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].excludes[]`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > excludes

A list of subdirectories to mask with emptyDir volumes. Each entry is a path relative to `containerPath`. This is useful when the host mount would overlay directories that were populated during the image build (e.g. `node_modules`, Python virtualenvs). The container sees an initially empty directory at each excluded path and can repopulate it at startup.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `helm` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |


# kubernetes Deploy

## Description

Specify one or more Kubernetes manifests to deploy.

You can either (or both) specify the manifests as part of the `garden.yml` configuration, or you can refer to one or more files with existing manifests.

Note that if you include the manifests in the `garden.yml` file, you can use [template strings](https://docs.garden.io/cedar-0.14/features/variables-and-templating) to interpolate values into the manifests.

If you need more advanced templating features you can use the [helm](/reference/action-types/deploy/helm) Deploy type.

Below is the full schema reference for the action.

`kubernetes` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.kustomize`

[spec](#spec) > kustomize

Resolve the specified kustomization and include the resulting resources. Note that if you specify `files` or `manifests` as well, these are also included.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.kustomize.path`

[spec](#spec) > [kustomize](#speckustomize) > path

The directory path where the desired kustomization.yaml is, or a git repository URL. This could be the path to an overlay directory, for example. If it's a path, must be a relative POSIX-style path and must be within the action root. Defaults to the action root. If you set this to null, kustomize will not be run.

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `posixPath \| string` | `"."`   | No       |

### `spec.kustomize.version`

[spec](#spec) > [kustomize](#speckustomize) > version

The Kustomize version to use.

| Type     | Allowed Values | Default | Required |
| -------- | -------------- | ------- | -------- |
| `number` | 4, 5           | `5`     | Yes      |

### `spec.kustomize.extraArgs[]`

[spec](#spec) > [kustomize](#speckustomize) > extraArgs

A list of additional arguments to pass to the `kustomize build` command. Note that specifying '-o' or '--output' is not allowed.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `spec.manifests[]`

[spec](#spec) > manifests

List of Kubernetes resource manifests to deploy. If `files` is also specified, this is combined with the manifests read from the files.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.manifests[].apiVersion`

[spec](#spec) > [manifests](#specmanifests) > apiVersion

The API version of the resource.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.manifests[].kind`

[spec](#spec) > [manifests](#specmanifests) > kind

The kind of the resource.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.manifests[].metadata`

[spec](#spec) > [manifests](#specmanifests) > metadata

| Type     | Required |
| -------- | -------- |
| `object` | Yes      |

### `spec.manifests[].metadata.name`

[spec](#spec) > [manifests](#specmanifests) > [metadata](#specmanifestsmetadata) > name

The name of the resource.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.patchResources[]`

[spec](#spec) > patchResources

A list of resources to patch using Kubernetes' patch strategies. This is useful for e.g. overwriting a given container image name with an image built by Garden without having to actually modify the underlying Kubernetes manifest in your source code. Another common example is to use this to change the number of replicas for a given Kubernetes Deployment.

Under the hood, Garden just applies the `kubectl patch` command to the resource that matches the specified `kind` and `name`.

Patches are applied to file manifests, inline manifests, and kustomize files.

You can learn more about patching Kubernetes resources here: <https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/>

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.patchResources[].kind`

[spec](#spec) > [patchResources](#specpatchresources) > kind

The kind of the resource to patch.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.patchResources[].name`

[spec](#spec) > [patchResources](#specpatchresources) > name

The name of the resource to patch.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.patchResources[].strategy`

[spec](#spec) > [patchResources](#specpatchresources) > strategy

The patch strategy to use. One of 'json', 'merge', or 'strategic'. Defaults to 'strategic'.

You can read more about the different strategies in the official Kubernetes documentation at: <https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/>

| Type     | Default       | Required |
| -------- | ------------- | -------- |
| `string` | `"strategic"` | No       |

### `spec.patchResources[].patch`

[spec](#spec) > [patchResources](#specpatchresources) > patch

The patch to apply.

| Type     | Required |
| -------- | -------- |
| `object` | Yes      |

### `spec.namespace`

[spec](#spec) > namespace

A valid Kubernetes namespace name. Must be a valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, and cannot end with a dash) and must not be longer than 63 characters.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.portForwards[]`

[spec](#spec) > portForwards

Manually specify port forwards that Garden should set up when deploying in dev or watch mode. If specified, these override the auto-detection of forwardable ports, so you'll need to specify the full list of port forwards to create.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.portForwards[].name`

[spec](#spec) > [portForwards](#specportforwards) > name

An identifier to describe the port forward.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.portForwards[].resource`

[spec](#spec) > [portForwards](#specportforwards) > resource

The full resource kind and name to forward to, e.g. Service/my-service or Deployment/my-deployment. Note that Garden will not validate this ahead of attempting to start the port forward, so you need to make sure this is correctly set. The types of resources supported will match that of the `kubectl port-forward` CLI command.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.portForwards[].targetPort`

[spec](#spec) > [portForwards](#specportforwards) > targetPort

The port number on the remote resource to forward to.

| Type     | Required |
| -------- | -------- |
| `number` | Yes      |

### `spec.portForwards[].localPort`

[spec](#spec) > [portForwards](#specportforwards) > localPort

The *preferred* local port to forward from. If none is set, a random port is chosen. If the specified port is not available, a warning is shown and a random port chosen instead.

| Type     | Required |
| -------- | -------- |
| `number` | No       |

### `spec.timeout`

[spec](#spec) > timeout

The maximum duration (in seconds) to wait for resources to deploy and become healthy.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `spec.applyArgs[]`

[spec](#spec) > applyArgs

Additional arguments to pass to `kubectl apply`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.waitForJobs`

[spec](#spec) > waitForJobs

Wait until the jobs have been completed. Garden will wait for as long as `timeout`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec.defaultTarget`

[spec](#spec) > defaultTarget

Specify a default resource in the deployment to use for syncs and for the `garden exec` command.

Specify either `kind` and `name`, or a `podSelector`. The resource should be one of the resources deployed by this action (otherwise the target is not guaranteed to be deployed with adjustments required for syncing).

Set `containerName` to specify a container to connect to in the remote Pod. By default the first container in the Pod is used.

Note that if you specify `podSelector` here, it is not validated to be a selector matching one of the resources deployed by the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.defaultTarget.kind`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.defaultTarget.name`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.defaultTarget.podSelector`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.defaultTarget.containerName`

[spec](#spec) > [defaultTarget](#specdefaulttarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync`

[spec](#spec) > sync

Configure path syncs for the resources in this Deploy.

If you have multiple syncs for the Deploy, you can use the `defaults` field to set common configuration for every individual sync.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.defaults`

[spec](#spec) > [sync](#specsync) > defaults

Defaults to set across every sync for this Deploy. If you use the `exclude` field here, it will be merged with any excludes set in individual syncs. These are applied on top of any defaults set in the provider configuration.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.defaults.exclude[]`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

Any exclusion patterns defined in individual sync specs will be applied in addition to these patterns.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    defaults:
      ...
      exclude:
        - dist/**/*
        - '*.log'
```

### `spec.sync.defaults.fileMode`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > fileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `spec.sync.defaults.directoryMode`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > directoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `spec.sync.defaults.owner`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > owner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.defaults.group`

[spec](#spec) > [sync](#specsync) > [defaults](#specsyncdefaults) > group

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.paths[]`

[spec](#spec) > [sync](#specsync) > paths

A list of syncs to start once the Deploy is successfully started.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.sync.paths[].target`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > target

The Kubernetes resource to sync to. If specified, this is used instead of `spec.defaultTarget`.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.paths[].target.kind`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.sync.paths[].target.name`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.paths[].target.podSelector`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.paths[].target.containerName`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > [target](#specsyncpathstarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.paths[].sourcePath`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > sourcePath

Path to a local directory to be synchronized with the target. This should generally be a templated path to another action's source path (e.g. `${actions.build.my-container-image.sourcePath}`), or a relative path. If a path is hard-coded, we recommend sticking with relative paths here, and using forward slashes (`/`) as a delimiter, as Windows-style paths with back slashes (`\`) and absolute paths will work on some platforms, but they are not portable and will not work for users on other platforms. Defaults to the Deploy action's config's directory if no value is provided.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"."`   | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - sourcePath: "src"
```

### `spec.sync.paths[].containerPath`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > containerPath

POSIX-style absolute path to sync to inside the container. The root path (i.e. "/") is not allowed.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - containerPath: "/app/src"
```

### `spec.sync.paths[].exclude[]`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > exclude

Specify a list of POSIX-style paths or glob patterns that should be excluded from the sync.

`.git` directories and `.garden` directories are always ignored.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
spec:
  ...
  sync:
    ...
    paths:
      - exclude:
          - dist/**/*
          - '*.log'
```

### `spec.sync.paths[].mode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > mode

The sync mode to use for the given paths. See the [Code Synchronization guide](https://docs.garden.io/cedar-0.14/guides/code-synchronization) for details.

| Type     | Allowed Values                                                                                                                            | Default          | Required |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- |
| `string` | "one-way", "one-way-safe", "one-way-replica", "one-way-reverse", "one-way-replica-reverse", "two-way", "two-way-safe", "two-way-resolved" | `"one-way-safe"` | Yes      |

### `spec.sync.paths[].defaultFileMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultFileMode

The default permission bits, specified as an octal, to set on files at the sync target. Defaults to 0o644 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o644` | No       |

### `spec.sync.paths[].defaultDirectoryMode`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultDirectoryMode

The default permission bits, specified as an octal, to set on directories at the sync target. Defaults to 0o755 (user can read/write, everyone else can read). See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#permissions) for more information.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `0o755` | No       |

### `spec.sync.paths[].defaultOwner`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultOwner

Set the default owner of files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.paths[].defaultGroup`

[spec](#spec) > [sync](#specsync) > [paths](#specsyncpaths) > defaultGroup

Set the default group on files and directories at the target. Specify either an integer ID or a string name. See the [Mutagen docs](https://mutagen.io/documentation/synchronization/permissions#owners-and-groups) for more information.

| Type               | Required |
| ------------------ | -------- |
| `number \| string` | No       |

### `spec.sync.overrides[]`

[spec](#spec) > [sync](#specsync) > overrides

Overrides for the container command and/or arguments for when in sync mode.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

### `spec.sync.overrides[].target`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > target

The Kubernetes resources to override. If specified, this is used instead of `spec.defaultTarget`.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.overrides[].target.kind`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > kind

The kind of Kubernetes resource to find.

| Type     | Allowed Values                           | Required |
| -------- | ---------------------------------------- | -------- |
| `string` | "Deployment", "DaemonSet", "StatefulSet" | Yes      |

### `spec.sync.overrides[].target.name`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > name

The name of the resource, of the specified `kind`. If specified, you must also specify `kind`.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.overrides[].target.podSelector`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > podSelector

A map of string key/value labels to match on any Pods in the namespace. When specified, a random ready Pod with matching labels will be picked as a target, so make sure the labels will always match a specific Pod type.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.sync.overrides[].target.containerName`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > [target](#specsyncoverridestarget) > containerName

The name of a container in the target. Specify this if the target contains more than one container and the main container is not the first container in the spec.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.sync.overrides[].command[]`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > command

Override the command/entrypoint in the matched container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.overrides[].args[]`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > args

Override the args in the matched container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.sync.overrides[].image`

[spec](#spec) > [sync](#specsync) > [overrides](#specsyncoverrides) > image

Override the image of the matched container.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.localVolumes`

[spec](#spec) > localVolumes

**Experimental**: Configure local host volume mounts for development. When enabled, Garden injects hostPath volumes into the target workloads, mapping local directories into containers. This is useful for local development where you want to mount source code directly instead of using file sync.

Garden automatically converts host paths to the correct format based on the local Kubernetes cluster type (Docker Desktop, kind, minikube, Orbstack) and OS (macOS, Linux, Windows).

Note: This feature is still experimental and its configuration format may change in future releases.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localVolumes.enabled`

[spec](#spec) > [localVolumes](#speclocalvolumes) > enabled

Whether local volume mounts are enabled for this action. Defaults to true when volumes are defined.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.localVolumes.volumes[]`

[spec](#spec) > [localVolumes](#speclocalvolumes) > volumes

List of local volumes to mount into the target resource(s). Each volume maps a host directory to a container path in the specified target workload.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.localVolumes.volumes[].name`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > name

A unique name for this volume mount.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > target

The target resource to mount this volume into. Overrides `spec.defaultTarget` if set.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.localVolumes.volumes[].target.kind`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > kind

The kind of the target resource (e.g. Deployment, StatefulSet).

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target.name`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > name

The name of the target resource.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].target.containerName`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > [target](#speclocalvolumesvolumestarget) > containerName

The name of the container to mount the volume into. Defaults to the first container.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.localVolumes.volumes[].sourcePath`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > sourcePath

The path on the host, relative to the action source directory, to mount into the container.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `spec.localVolumes.volumes[].containerPath`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > containerPath

The absolute path inside the container where the volume should be mounted.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.localVolumes.volumes[].excludes[]`

[spec](#spec) > [localVolumes](#speclocalvolumes) > [volumes](#speclocalvolumesvolumes) > excludes

A list of subdirectories to mask with emptyDir volumes. Each entry is a path relative to `containerPath`. This is useful when the host mount would overlay directories that were populated during the image build (e.g. `node_modules`, Python virtualenvs). The container sees an initially empty directory at each excluded path and can repopulate it at startup.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.manifestFiles[]`

[spec](#spec) > manifestFiles

POSIX-style paths to YAML files to load manifests from. Garden will *not* use the Garden Template Language to transform manifests in these files. Each file can contain multiple manifests.

| Type               | Default | Required |
| ------------------ | ------- | -------- |
| `array[posixPath]` | `[]`    | No       |

### `spec.manifestTemplates[]`

[spec](#spec) > manifestTemplates

POSIX-style paths to YAML files to load manifests from. Each can contain multiple manifests, and can include any Garden template strings, which will be resolved before applying the manifests.

| Type               | Default | Required |
| ------------------ | ------- | -------- |
| `array[posixPath]` | `[]`    | No       |

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `kubernetes` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |


# pulumi Deploy

## Description

Deploys a Pulumi stack and either creates/updates it automatically (if `autoApply: true`) or warns when the stack resources are not up-to-date, or errors if it's missing entirely.

**Note: It is not recommended to set `autoApply` to `true` for production or shared environments, since this may result in accidental or conflicting changes to the stack.** Instead, it is recommended to manually preview and update using the provided plugin commands. Run `garden plugins pulumi` for details. Note that not all Pulumi CLI commands are wrapped by the plugin, only the ones where it's important to apply any variables defined in the action. For others, simply run the Pulumi CLI as usual from the project root.

Stack outputs are made available as action outputs. These can then be referenced by other actions under `${actions.<action-kind>.<action-name>.outputs.<key>}`. You can template in those values as e.g. command arguments or environment variables for other services.

Below is the full schema reference for the action.

`pulumi` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.allowDestroy`

[spec](#spec) > allowDestroy

If set to true, Garden will destroy the stack when calling `garden cleanup namespace` or `garden cleanup deploy <deploy action name>`. This is useful to prevent unintentional destroys in production or shared environments.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec.autoApply`

[spec](#spec) > autoApply

If set to false, deployments will fail unless a `planPath` is provided for this deploy action. This is useful when deploying to production or shared environments, or when the action deploys infrastructure that you don't want to unintentionally update/create.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec.createStack`

[spec](#spec) > createStack

If set to true, Garden will automatically create the stack if it doesn't already exist.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.root`

[spec](#spec) > root

Specify the path to the Pulumi project root, relative to the deploy action's root.

| Type        | Default | Required |
| ----------- | ------- | -------- |
| `posixPath` | `"."`   | No       |

### `spec.useNewPulumiVarfileSchema`

[spec](#spec) > useNewPulumiVarfileSchema

If set to true, the deploy action will use the new Pulumi varfile schema, which does not nest all variables under the 'config' key automatically like the old schema. This allow setting variables at the root level of the varfile that don't belong to the 'config' key. Example:

```
config:
  myVar: value
secretsprovider: gcpkms://projects/xyz/locations/global/keyRings/pulumi/cryptoKeys/pulumi-secrets
```

For more information see [this guide on pulumi varfiles and variables](https://docs.garden.io/pulumi-plugin/about#pulumi-varfile-schema)

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.pulumiVariables`

[spec](#spec) > pulumiVariables

A map of config variables to use when applying the stack. These are merged with the contents of any `pulumiVarfiles` provided for this deploy action. The deploy action's stack config will be overwritten with the resulting merged config. Variables declared here override any conflicting config variables defined in this deploy action's `pulumiVarfiles`.

Note: `pulumiVariables` should not include action outputs from other pulumi deploy actions when `cacheStatus` is set to true, since the outputs may change from the time the stack status of the dependency action is initially queried to when it's been deployed.

Instead, use pulumi stack references when using the `cacheStatus` config option.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

### `spec.pulumiVarfiles[]`

[spec](#spec) > pulumiVarfiles

Specify one or more paths (relative to the deploy action's root) to YAML files containing pulumi configuration.

Templated paths that resolve to `null`, `undefined` or an empty string are ignored.

Any Garden template strings in these varfiles will be resolved when the files are loaded.

Each file must consist of a single YAML document, which must be a map (dictionary). Keys may contain any value type.

If one or more varfiles is not found, no error is thrown (that varfile path is simply ignored).

Note: The old varfile schema nests all variables under the 'config' key automatically. If you need to set variables at the root level of the varfile that don't belong to the 'config' key, set `useNewPulumiVarfileSchema` to true.

| Type               | Default | Required |
| ------------------ | ------- | -------- |
| `array[posixPath]` | `[]`    | No       |

### `spec.orgName`

[spec](#spec) > orgName

The name of the pulumi organization to use. Overrides the `orgName` set on the pulumi provider (if any). To use the default org, set to null.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.cacheStatus`

[spec](#spec) > cacheStatus

When set to true, the pulumi stack will be tagged with the Garden service version when deploying. The tag will then be used for service status checks for this service. If the version doesn't change between deploys, the subsequent deploy is skipped.

Note that this will not pick up changes to stack outputs referenced via stack references in your pulumi stack, unless they're referenced via template strings in the deploy action configuration.

When using stack references to other pulumi deploy actions in your project, we recommend including them in this deploy action's `stackReferences` config field (see the documentation for that field on this page).

`cacheStatus: true` is not supported for self-managed state backends.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.stackReferences[]`

[spec](#spec) > stackReferences

When setting `cacheStatus` to true for this deploy action, you should include all stack references used by this deploy action's pulumi stack in this field.

This lets Garden know to redeploy the pulumi stack if the output values of one or more of these stack references have changed since the last deployment.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

Example:

```yaml
spec:
  ...
  stackReferences:
    - ${actions.deploy.some-pulumi-deploy-action.outputs.ip-address}
    - ${actions.deploy.some-other-pulumi-deploy-action.outputs.database-url}
```

### `spec.deployFromPreview`

[spec](#spec) > deployFromPreview

When set to true, will use pulumi plans generated by the `garden plugins pulumi preview` command when deploying, and will fail if no plan exists locally for the deploy action.

When this option is used, the pulumi plugin bypasses the status check altogether and passes the plan directly to `pulumi up` (via the `--plan` option, which is experimental as of March 2022). You should therefore take care to only use this config option when you're sure you want to apply the changes in the plan.

This option is intended for two-phase pulumi deployments, where pulumi preview diffs are first reviewed (e.g. during code review).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.stack`

[spec](#spec) > stack

The name of the pulumi stack to use. Defaults to the current environment name.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.showSecretsInOutput`

[spec](#spec) > showSecretsInOutput

When set to true, stack outputs which are marked as secrets will be shown in the output.

By default, Pulumi will print secret stack outputs as the string '\[secret]' instead of the true content of the output.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `pulumi` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.deploy.<name>.outputs.*}`

A map of all the outputs returned by the Pulumi stack.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.outputs.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |


# terraform Deploy

## Description

Resolves a Terraform stack and either applies it automatically (if `autoApply: true`) or warns when the stack resources are not up-to-date.

**Note: It is not recommended to set `autoApply` to `true` for any production or shared environments, since this may result in accidental or conflicting changes to the stack.** Instead, it is recommended to manually plan and apply using the provided plugin commands. Run `garden plugins terraform` for details.

Stack outputs are made available as service outputs, that can be referenced by other actions under `${deploys.<deploy-name>.outputs.<key>}`. You can template in those values as e.g. command arguments or environment variables for other services.

Note that you can also declare a Terraform root in the `terraform` provider configuration by setting the `initRoot` parameter. This may be preferable if you need the outputs of the Terraform stack to be available to other provider configurations, e.g. if you spin up an environment with the Terraform provider, and then use outputs from that to configure another provider or other actions via `${providers.terraform.outputs.<key>}` template strings.

See the [Terraform guide](https://docs.garden.io/cedar-0.14/advanced/terraform) for a high-level introduction to the `terraform` provider.

Below is the full schema reference for the action.

`terraform` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Deploy"       | Yes      |

### `timeout`

Timeout for the deploy to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `300`   | No       |

### `removeOnCleanup`

Set this to `false` to prevent this Deploy from being removed during `garden cleanup deploy` or `garden cleanup namespace` commands. This is useful for preventing the cleanup of persistent resources like PVCs or databases during cleanup operations.

Use the `--force` flag on the cleanup commands to override this and clean up deploys regardless of this flag.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.allowDestroy`

[spec](#spec) > allowDestroy

If set to true, Garden will run `terraform destroy` on the stack when calling `garden delete namespace` or `garden delete deploy <deploy name>`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.autoApply`

[spec](#spec) > autoApply

If set to true, Garden will automatically run `terraform apply -auto-approve` when the stack is not up-to-date. Otherwise, a warning is logged if the stack is out-of-date, and an error thrown if it is missing entirely.

**NOTE: This is not recommended for production, or shared environments in general!**

Defaults to the value set in the provider config.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `null`  | No       |

### `spec.root`

[spec](#spec) > root

Specify the path to the working directory root—i.e. where your Terraform files are—relative to the config directory.

| Type        | Default | Required |
| ----------- | ------- | -------- |
| `posixPath` | `"."`   | No       |

### `spec.variables`

[spec](#spec) > variables

A map of variables to use when applying the stack. You can define these here or you can place a `terraform.tfvars` file in the working directory root.

If you specified `variables` in the `terraform` provider config, those will be included but the variables specified here take precedence.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.version`

[spec](#spec) > version

The version of Terraform to use. Defaults to the version set in the provider config. Set to `null` to use whichever version of `terraform` that is on your PATH.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.workspace`

[spec](#spec) > workspace

Use the specified Terraform workspace.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.backendConfig`

[spec](#spec) > backendConfig

Configure the Terraform backend.

The key-value pairs defined here are set as the `-backend-config` options when Garden runs `terraform init`.

This can be used to dynamically set a Terraform backend depending on the environment.

If Garden sees that the backend has changes, it'll re-initialize Terraform and set the new values.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

Example:

```yaml
spec:
  ...
  backendConfig:
      bucket: ${environment.name}-bucket
      key: tf-state/${local.username}/terraform.tfstate
```

## Outputs

The following keys are available via the `${actions.deploy.<name>}` template string key for `terraform` action.

### `${actions.deploy.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.deploy.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.disabled}
```

### `${actions.deploy.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.buildPath}
```

### `${actions.deploy.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.sourcePath}
```

### `${actions.deploy.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.deploy.my-deploy.mode}
```

### `${actions.deploy.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.deploy.<name>.outputs.*}`

A map of all the outputs defined in the Terraform stack.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.deploy.<name>.outputs.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |


# Run

* [`container`](/reference/action-types/run/container)
* [`kubernetes-exec`](/reference/action-types/run/kubernetes-exec)
* [`kubernetes-pod`](/reference/action-types/run/kubernetes-pod)
* [`helm-pod`](/reference/action-types/run/helm-pod)
* [`exec`](/reference/action-types/run/exec)


# container Run

## Description

Run a command in a container image, e.g. in a Kubernetes namespace (when used with the `kubernetes` provider).

This is a simplified abstraction, which can be convenient for simple tasks, but has limited features compared to more platform-specific types. For example, you cannot specify replicas for redundancy, and various platform-specific options are not included. For more flexibility, please look at other Run types like [kubernetes-pod](/reference/action-types/run/kubernetes-pod).

Below is the full schema reference for the action.

`container` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Run"          | Yes      |

### `timeout`

Set a timeout for the run to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `600`   | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.command[]`

[spec](#spec) > command

The command/entrypoint to run the container with.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
spec:
  ...
  command:
    - /bin/sh
    - '-c'
```

### `spec.args[]`

[spec](#spec) > args

The arguments (on top of the `command`, i.e. entrypoint) to run the container with.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

Example:

```yaml
spec:
  ...
  args:
    - npm
    - start
```

### `spec.env`

[spec](#spec) > env

Key/value map of environment variables. Keys must be valid POSIX environment variable names (must not start with `GARDEN`) and values must be primitives or references to secrets.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

Example:

```yaml
spec:
  ...
  env:
      - MY_VAR: some-value
        MY_SECRET_VAR:
          secretRef:
            name: my-secret
            key: some-key
      - {}
```

### `spec.cpu`

[spec](#spec) > cpu

| Type     | Default                 | Required |
| -------- | ----------------------- | -------- |
| `object` | `{"min":10,"max":1000}` | No       |

### `spec.cpu.min`

[spec](#spec) > [cpu](#speccpu) > min

The minimum amount of CPU the container needs to be available for it to be deployed, in millicpus (i.e. 1000 = 1 CPU)

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `10`    | No       |

### `spec.cpu.max`

[spec](#spec) > [cpu](#speccpu) > max

The maximum amount of CPU the container can use, in millicpus (i.e. 1000 = 1 CPU). If set to null will result in no limit being set.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `1000`  | No       |

### `spec.memory`

[spec](#spec) > memory

| Type     | Default                 | Required |
| -------- | ----------------------- | -------- |
| `object` | `{"min":90,"max":1024}` | No       |

### `spec.memory.min`

[spec](#spec) > [memory](#specmemory) > min

The minimum amount of RAM the container needs to be available for it to be deployed, in megabytes (i.e. 1024 = 1 GB)

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `90`    | No       |

### `spec.memory.max`

[spec](#spec) > [memory](#specmemory) > max

The maximum amount of RAM the container can use, in megabytes (i.e. 1024 = 1 GB) If set to null will result in no limit being set.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `1024`  | No       |

### `spec.volumes[]`

[spec](#spec) > volumes

List of volumes that should be mounted when starting the container.

Note: If neither `hostPath` nor `action` is specified, an empty ephemeral volume is created and mounted when deploying the container.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[object]` | `[]`    | No       |

### `spec.volumes[].name`

[spec](#spec) > [volumes](#specvolumes) > name

The name of the allocated volume.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.volumes[].containerPath`

[spec](#spec) > [volumes](#specvolumes) > containerPath

The path where the volume should be mounted in the container.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `spec.volumes[].hostPath`

[spec](#spec) > [volumes](#specvolumes) > hostPath

*NOTE: Usage of hostPath is generally discouraged, since it doesn't work reliably across different platforms and providers. Some providers may not support it at all.*

A local path or path on the node that's running the container, to mount in the container, relative to the config source directory (or absolute).

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

Example:

```yaml
spec:
  ...
  volumes:
    - hostPath: "/some/dir"
```

### `spec.privileged`

[spec](#spec) > privileged

If true, run the main container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.addCapabilities[]`

[spec](#spec) > addCapabilities

POSIX capabilities to add when running the container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.dropCapabilities[]`

[spec](#spec) > dropCapabilities

POSIX capabilities to remove when running the container.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `spec.tty`

[spec](#spec) > tty

Specify if containers in this action have TTY support enabled (which implies having stdin support enabled).

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `spec.deploymentStrategy`

[spec](#spec) > deploymentStrategy

Specifies the container's deployment strategy.

| Type     | Allowed Values              | Default           | Required |
| -------- | --------------------------- | ----------------- | -------- |
| `string` | "RollingUpdate", "Recreate" | `"RollingUpdate"` | Yes      |

### `spec.artifacts[]`

[spec](#spec) > artifacts

Specify artifacts to copy out of the container after the run. The artifacts are stored locally under the `.garden/artifacts` directory.

Note: Depending on the provider, this may require the container image to include `sh` `tar`, in order to enable the file transfer.

| Type            | Required |
| --------------- | -------- |
| `array[object]` | No       |

Example:

```yaml
spec:
  ...
  artifacts:
    - source: /report/**/*
```

### `spec.artifacts[].source`

[spec](#spec) > [artifacts](#specartifacts) > source

A POSIX-style path or glob to copy. Must be an absolute path. May contain wildcards.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

Example:

```yaml
spec:
  ...
  artifacts:
    - source: /report/**/*
    - source: "/output/**/*"
```

### `spec.artifacts[].target`

[spec](#spec) > [artifacts](#specartifacts) > target

A POSIX-style path to copy the artifacts to, relative to the project artifacts directory at `.garden/artifacts`.

| Type        | Default | Required |
| ----------- | ------- | -------- |
| `posixPath` | `"."`   | No       |

Example:

```yaml
spec:
  ...
  artifacts:
    - source: /report/**/*
    - target: "outputs/foo/"
```

### `spec.image`

[spec](#spec) > image

Specify an image ID to deploy. Should be a valid Docker image identifier. Required.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `spec.cacheResult`

[spec](#spec) > cacheResult

Set to false if you don't want the Run action result to be cached. Use this if the Run action needs to be run any time your project (or one or more of the Run action's dependants) is deployed. Otherwise the Run action is only re-run when its version changes, or when you run `garden run`.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `true`  | No       |

## Outputs

The following keys are available via the `${actions.run.<name>}` template string key for `container` action.

### `${actions.run.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.run.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.run.my-run.disabled}
```

### `${actions.run.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.run.my-run.buildPath}
```

### `${actions.run.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.run.my-run.sourcePath}
```

### `${actions.run.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.run.my-run.mode}
```

### `${actions.run.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.run.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.run.<name>.outputs.log}`

The full log output from the executed action. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |


# exec Run

## Description

A simple Run action which runs a command locally with a shell command.

Below is the full schema reference for the action.

`exec` actions also export values that are available in template strings. See the [Outputs](#outputs) section below for details.

## Configuration Keys

### `type`

The type of action, e.g. `exec`, `container` or `kubernetes`. Some are built into Garden but mostly these will be defined by your configured providers.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `name`

A valid name for the action. Must be unique across all actions of the same *kind* in your project.

| Type     | Required |
| -------- | -------- |
| `string` | Yes      |

### `description`

A description of the action.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `source`

By default, the directory where the action is defined is used as the source for the build context.

You can override the directory that is used for the build context by setting `source.path`.

You can use `source.repository` to get the source from an external repository. For more information on remote actions, please refer to the [Remote Sources guide](https://docs.garden.io/cedar-0.14/advanced/using-remote-sources).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.path`

[source](#source) > path

A relative POSIX-style path to the source directory for this action.

If specified together with `source.repository`, the path will be relative to the repository root.

Otherwise, the path will be relative to the directory containing the Garden configuration file.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | No       |

### `source.repository`

[source](#source) > repository

When set, Garden will import the action source from this repository, but use this action configuration (and not scan for configs in the separate repository).

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `source.repository.url`

[source](#source) > [repository](#sourcerepository) > url

A remote repository URL. Currently only supports git servers. Must contain a hash suffix pointing to a specific branch or tag, with the format: #\<branch|tag>

| Type               | Required |
| ------------------ | -------- |
| `gitUrl \| string` | Yes      |

Example:

```yaml
source:
  ...
  repository:
    ...
    url: "git+https://github.com/org/repo.git#v2.0"
```

### `dependencies[]`

A list of other actions that this action depends on, and should be built, deployed or run (depending on the action type) before processing this action.

Each dependency should generally be expressed as a `"<kind>.<name>"` string, where is one of `build`, `deploy`, `run` or `test`, and is the name of the action to depend on.

You may also optionally specify a dependency as an object, e.g. `{ kind: "Build", name: "some-image" }`.

Any empty values (i.e. null or empty strings) are ignored, so that you can conditionally add in a dependency via template expressions.

| Type                     | Default | Required |
| ------------------------ | ------- | -------- |
| `array[actionReference]` | `[]`    | No       |

Example:

```yaml
dependencies:
  - build.my-image
  - deploy.api
```

### `disabled`

Set this to `true` to disable the action. You can use this with conditional template strings to disable actions based on, for example, the current environment or other variables (e.g. `disabled: ${environment.name == "prod"}`). This can be handy when you only need certain actions for specific environments, e.g. only for development.

For Build actions, this means the build is not performed *unless* it is declared as a dependency by another enabled action (in which case the Build is assumed to be necessary for the dependant action to be run or built).

For other action kinds, the action is skipped in all scenarios, and dependency declarations to it are ignored. Note however that template strings referencing outputs (i.e. runtime outputs) will fail to resolve when the action is disabled, so you need to make sure to provide alternate values for those if you're using them, using conditional expressions.

| Type      | Default | Required |
| --------- | ------- | -------- |
| `boolean` | `false` | No       |

### `environments[]`

If set, the action is only enabled for the listed environment types. This is effectively a cleaner shorthand for the `disabled` field with an expression for environments. For example, `environments: ["prod"]` is equivalent to `disabled: ${environment.name != "prod"}`.

| Type            | Required |
| --------------- | -------- |
| `array[string]` | No       |

### `logLevel`

Set the log level for this action. If not set, the action inherits the log level set for the command being executed.

Setting this can be useful for actions that produce a lot of log output that is not relevant to the user, or when debugging a specific action.

The `silent` level effectively suppresses log output from this action, except for errors.

| Type     | Allowed Values                                                 | Required |
| -------- | -------------------------------------------------------------- | -------- |
| `string` | "error", "warn", "info", "verbose", "debug", "silly", "silent" | Yes      |

### `include[]`

Specify a list of POSIX-style paths or globs that should be regarded as source files for this action, and thus will affect the computed *version* of the action.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. An exception would be e.g. an `exec` action without a `build` reference, where the relevant files cannot be inferred and you want to define which files should affect the version of the action, e.g. to make sure a Test action is run when certain files are modified.

*Build* actions have a different behavior, since they generally are based on some files in the source tree, so please reference the docs for more information on those.

Note that you can also *exclude* files using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
include:
  - my-app.js
  - some-assets/**/*
```

### `exclude[]`

Specify a list of POSIX-style paths or glob patterns that should be explicitly excluded from the action's version.

For actions other than *Build* actions, this is usually not necessary to specify, or is implicitly inferred. For *Deploy*, *Run* and *Test* actions, the exclusions specified here only applied on top of explicitly set `include` paths, or such paths inferred by providers. See the [Configuration Files guide](https://docs.garden.io/cedar-0.14/guides/configuration-overview#including-excluding-files-and-directories) for details.

Unlike the `scan.exclude` field in the project config, the filters here have *no effect* on which files and directories are watched for changes when watching is enabled. Use the project `scan.exclude` field to affect those, if you have large directories that should not be watched for changes.

| Type               | Required |
| ------------------ | -------- |
| `array[posixPath]` | No       |

Example:

```yaml
exclude:
  - tmp/**/*
  - '*.log'
```

### `variables`

A map of variables scoped to this particular action. These are resolved before any other parts of the action configuration and take precedence over group-scoped variables (if applicable) and project-scoped variables, in that order. They may reference group-scoped and project-scoped variables, and generally can use any template strings normally allowed when resolving the action.

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `varfiles[]`

Specify a list of paths (relative to the directory where the action is defined) to a file containing variables, that we apply on top of the action-level `variables` field, and take precedence over group-level variables (if applicable) and project-level variables, in that order.

If you specify multiple paths, they are merged in the order specified, i.e. the last one takes precedence over the previous ones.

The format of the files is determined by the configured file's extension:

* `.yaml`/`.yml` - YAML. The file must consist of a YAML document, which must be a map (dictionary). Keys may contain any value type. YAML format is used by default.
* `.env` - Standard "dotenv" format, as defined by [dotenv](https://github.com/motdotla/dotenv#rules).
* `.json` - JSON. Must contain a single JSON *object* (not an array).

*NOTE: The default varfile format was changed to YAML in Garden v0.13, since YAML allows for definition of nested objects and arrays.*

To use different varfiles in different environments, you can template in the environment name to the varfile name, e.g. `varfile: "my-action.${environment.name}.env"` (this assumes that the corresponding varfiles exist).

If a listed varfile cannot be found, throwing an error. To add optional varfiles, you can use a list item object with a `path` and an optional `optional` boolean field.

```yaml
varfiles:
  - path: my-action.env
    optional: true
```

| Type                  | Default | Required |
| --------------------- | ------- | -------- |
| `array[alternatives]` | `[]`    | No       |

Example:

```yaml
varfiles:
  "my-action.env"
```

### `varfiles[].path`

[varfiles](#varfiles) > path

Path to a file containing a path.

| Type        | Required |
| ----------- | -------- |
| `posixPath` | Yes      |

### `varfiles[].optional`

[varfiles](#varfiles) > optional

Whether the varfile is optional.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `version`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `version.excludeDependencies[]`

[version](#version) > excludeDependencies

Specify a list of dependencies that should be ignored when computing the version hash for this action.

Generally, the versions of all dependencies (both implicit and explicitly specified) are used when computing the version hash for this action. However, there are cases where you might want to exclude certain dependencies from the version hash.

For example, you might have a dependency that naturally changes for every individual test or dev environment, such as a setup script that runs before the test. You could solve for that with something like this:

```yaml
version:
  excludeDependencies:
    - run.setup
```

Where `run.setup` refers to a Run action named `setup`. You can also use the full action reference for each dependency to exclude, e.g. `{ kind: "Run", name: "setup" }`.

| Type                     | Required |
| ------------------------ | -------- |
| `array[actionReference]` | No       |

### `version.excludeFields[]`

[version](#version) > excludeFields

Specify a list of config fields that should be ignored when computing the version hash for this action. Each item should be an array of strings, specifying the path to the field to ignore, e.g. `[spec, env, HOSTNAME]` would ignore `spec.env.HOSTNAME` in the configuration when computing the version.

For example, you might have a field that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeFields:
    - [spec, env, HOSTNAME]
```

Arrays can also be indexed with numeric indices, but you can also use wildcards to exclude specific fields on all objects in arrays. Example:

```yaml
kind: Test
type: container
...
spec:
  artifacts:
    - source: foo
      target: bar  # Gets excluded from the version calculation
version:
  excludeFields:
    - [spec, artifacts, "*", target]
```

Only simple `"*"` wildcards are supported for the moment (i.e. you can't exclude by `"something*"` or use question marks for individual character matching).

Note that it is very important not to specify overly broad exclusions here, as this may cause the version to change too rarely, which may cause build errors or tests to not run when they should.

| Type           | Required |
| -------------- | -------- |
| `array[array]` | No       |

### `version.excludeFiles[]`

[version](#version) > excludeFiles

Specify one or more file paths that should be ignored when computing the version hash for this action.

Specify in the same format as the `include` field. You may use glob patterns here.

For example, you might have a file that naturally changes for every build, such as a compiled binary (that isn't deterministic down to the byte), that you need to have in the build but shouldn't affect the version. You could solve for that with something like this:

```yaml
include:
  - src/**/*
  - some/compiled/binary
version:
  excludeFiles:
    - some/compiled/binary
```

Note that when you use this, you do need to make sure that other files or config fields do affect the version appropriately. Otherwise you might run into issues where builds are not updated or tests are not run when they should be.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `version.excludeValues[]`

[version](#version) > excludeValues

Specify one or more string values that should be ignored when computing the version hash for this action. You may use template expressions here. This is useful to avoid dynamic values affecting cache versions.

For example, you might have a variable that naturally changes for every individual test or dev environment, such as a dynamic hostname. You could solve for that with something like this:

```yaml
version:
  excludeValues:
    - ${var.hostname}
```

With the `hostname` variable being defined in the Project configuration.

For each value specified under this field, every occurrence of that string value (even as part of a longer string) will be replaced when calculating the action version. The action configuration (used when performing the action) is not affected.

For instances when the value to replace may be overly broad (e.g. "api") it is generally better to use the `excludeFields` option, since that can be applied more surgically.

| Type            | Default | Required |
| --------------- | ------- | -------- |
| `array[string]` | `[]`    | No       |

### `build`

Specify a *Build* action, and resolve this action from the context of that Build.

For example, you might create an `exec` Build which prepares some manifests, and then reference that in a `kubernetes` *Deploy* action, and the resulting manifests from the Build.

This would mean that instead of looking for manifest files relative to this action's location in your project structure, the output directory for the referenced `exec` Build would be the source.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `kind`

| Type     | Allowed Values | Required |
| -------- | -------------- | -------- |
| `string` | "Run"          | Yes      |

### `timeout`

Set a timeout for the run to complete, in seconds.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `number` | `600`   | No       |

### `spec`

| Type     | Required |
| -------- | -------- |
| `object` | No       |

### `spec.shell`

[spec](#spec) > shell

If `true`, runs file inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.

Note that if this is not set, no shell interpreter (Bash, `cmd.exe`, etc.) is used, so shell features such as variables substitution (`echo $PATH`) are not allowed.

We recommend against using this option since it is:

* not cross-platform, encouraging shell-specific syntax.
* slower, because of the additional shell interpretation.
* unsafe, potentially allowing command injection.

| Type      | Required |
| --------- | -------- |
| `boolean` | No       |

### `spec.artifacts[]`

[spec](#spec) > artifacts

A list of artifacts to copy after the run.

| Type    | Default | Required |
| ------- | ------- | -------- |
| `array` | `[]`    | No       |

### `spec.artifacts[].source`

[spec](#spec) > [artifacts](#specartifacts) > source

A POSIX-style path or glob to copy, relative to the build root.

| Type     | Required |
| -------- | -------- |
| `string` | No       |

### `spec.artifacts[].target`

[spec](#spec) > [artifacts](#specartifacts) > target

A POSIX-style path to copy the artifacts to, relative to the project artifacts directory at `.garden/artifacts`.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `string` | `"."`   | No       |

### `spec.command[]`

[spec](#spec) > command

The command to run.

**Action outputs**

Exec actions can write outputs to a JSON file or a directory. The action command is provided with the path to the outputs directory or JSON file via the `GARDEN_ACTION_OUTPUTS_PATH` or `GARDEN_ACTION_OUTPUTS_JSON_PATH` environment variables.

If you write a JSON file to `<GARDEN_ACTION_OUTPUTS_JSON_PATH>` this file will be read and its contents will be used as the action outputs. Nested JSON objects are not supported. Only the top-level key-value pairs, where values are primitive types (string, number, boolean, null), will be used.

You can also write outputs to files in the directory. In this scenario, each file with a valid identifier as a filename (this excludes paths starting with `.` for example) in the directory will be read and its filename will be added as the key in the action outputs, with the contents of the file as the value. Sub-directories are not supported and will be ignored. For example, if you write some string to `<GARDEN_ACTION_OUTPUTS_PATH>/my-output`, the action outputs will contain a `my-output` key with the value `<contents of my-output.txt>`.

It is allowed to mix and match between the two approaches. In that scenario the JSON file will be read first, and any additional valid filenames in the directory will be added as additional action outputs, overriding keys in the JSON file if they overlap.

Note that if you provide a `statusCommand`, the outputs will also be read from the directory after the status command is run. You'll need to ensure that the outputs are consistent between the status command and the command that is run, to avoid unexpected results.

**Build field**

Note that if a Build is referenced in the `build` field, the command will be run from the build directory for that Build action. If that Build has `buildAtSource: true` set, the command will be run from the source directory of the Build action. If no `build` reference is set, the command is run from the source directory of this action.

Example: `["npm","run","build"]`

| Type    | Required |
| ------- | -------- |
| `array` | Yes      |

### `spec.statusCommand[]`

[spec](#spec) > statusCommand

The command to run to check the status of the action.

If this is specified, it is run before the action's `command`. If the status command runs successfully and returns exit code of 0, the action is considered already complete and the `command` is not run. To indicate that the action is not complete, the status command should return a non-zero exit code.

If this is not specified, the status is always reported as "unknown", so specifying this can be useful to avoid running the action unnecessarily.

Action outputs are also read from the directory after the status command is run (if the status is "ready"). If your action command writes outputs when run, you'll need to ensure that the outputs are consistent between the status command and the main command, to avoid unexpected results.

| Type    | Required |
| ------- | -------- |
| `array` | No       |

### `spec.env`

[spec](#spec) > env

Environment variables to set when running the command.

| Type     | Default | Required |
| -------- | ------- | -------- |
| `object` | `{}`    | No       |

## Outputs

The following keys are available via the `${actions.run.<name>}` template string key for `exec` action.

### `${actions.run.<name>.name}`

The name of the action.

| Type     |
| -------- |
| `string` |

### `${actions.run.<name>.disabled}`

Whether the action is disabled.

| Type      |
| --------- |
| `boolean` |

Example:

```yaml
my-variable: ${actions.run.my-run.disabled}
```

### `${actions.run.<name>.buildPath}`

The local path to the action build directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.run.my-run.buildPath}
```

### `${actions.run.<name>.sourcePath}`

The local path to the action source directory.

| Type     |
| -------- |
| `string` |

Example:

```yaml
my-variable: ${actions.run.my-run.sourcePath}
```

### `${actions.run.<name>.mode}`

The mode that the action should be executed in (e.g. 'sync' or 'local' for Deploy actions). Set to 'default' if no special mode is being used.

Build actions inherit the mode from Deploy actions that depend on them. E.g. If a Deploy action is in 'sync' mode and depends on a Build action, the Build action will inherit the 'sync' mode setting from the Deploy action. This enables installing different tools that may be necessary for different development modes.

| Type     | Default     |
| -------- | ----------- |
| `string` | `"default"` |

Example:

```yaml
my-variable: ${actions.run.my-run.mode}
```

### `${actions.run.<name>.var.*}`

The variables configured on the action.

| Type     | Default |
| -------- | ------- |
| `object` | `{}`    |

### `${actions.run.<name>.var.<name>}`

| Type                                                 |
| ---------------------------------------------------- |
| `string \| number \| boolean \| link \| array[link]` |

### `${actions.run.<name>.outputs.log}`

The full log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.run.<name>.outputs.stdout}`

The stdout log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |

### `${actions.run.<name>.outputs.stderr}`

The stderr log output from the executed command. (Pro-tip: Make it machine readable so it can be parsed by dependants)

| Type     | Default |
| -------- | ------- |
| `string` | `""`    |




---

[Next Page](/llms-full.txt/1)

