> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Promotion

> Promote workloads across development, staging, and production environments using separate orgs and GitHub Actions workflows.

As a best practice, each deployment environment (development, staging, production, etc.) should map to a Control Plane [Org](/reference/org).

The primary benefit of having each environment under a separate [Org](/reference/org) is that definitions of different [GVCs](/reference/gvc) and [workloads](/reference/workload) can be applied to different [Orgs](/reference/org) without the need to include an environment name in any object.

For example, in the development [Org](/reference/org), you could apply nearly the same YAML manifest files (used by [cpln apply](/guides/cpln-apply)) as the production [Org](/reference/org) with different content for your secrets.

During the promotion process, the [image](/reference/image) that was built for development can be referred to by other [workloads](/reference/workload) in the same [Org](/reference/org) and across [Orgs](/reference/org). This is a great time saver for lengthy build processes.

## Promotion using GitHub Actions

By leveraging the functionality of [GitHub Actions](https://docs.github.com/en/actions), promoting code changes from one environment to another is as easy as committing/pushing your code and opening/merging pull requests.

This [example](https://github.com/controlplane-com/promotion-demo) project contains three GitHub Actions (in the `./.github/workflows` directory) that perform the following:

1. On a pull request (or updates to an existing pull request) to the `main` branch, the application is containerized and pushed to the dev [Org's](/reference/org) private [image registry](/reference/image). The [GVC](/reference/gvc) and `Review Workload` is created/updated by applying the YAML contents of the files `./cpln/cpln-gvc.yaml` and `./cpln/cpln-workload.yaml`. The name of the `Review Workload` will be prefixed by the name of the branch that created the pull request.
2. When a pull request is accepted and the code is merged to the `main` branch, a `dev` [workload](/reference/workload) is updated (or created if it doesn't exists) in the dev [Org](/reference/org) by applying the same files as step 1, except that the [workload](/reference/workload) name is prefixed with `dev`. This allows the application to be reviewed and tested before being pushed to the production [Org](/reference/org).
3. The promotion to the `stage` and `prod` environment is accomplished by manually executing the `Deploy-To-Stage-or-Prod` workflow and selecting the target environment. The target [GVC](/reference/gvc) and [Workload](/reference/workload) in the production [Org](/reference/org) is updated (or created if it doesn't exists) by applying the YAML contents of the files `./cpln/cpln-gvc-prod.yaml` and `./cpln/cpln-workload.yaml`. The main difference between the two [GVC](/reference/gvc) files is that the `prod` version contains the `Pull Secret` that is needed to pull the [image](/reference/image) from the dev [Org](/reference/org) and the `stage` and `prod` [workloads](/reference/workload) refer to the [image](/reference/image) that was pushed to the development [Org](/reference/org).

## Review Workload

The above example demonstrates the concept of a **Review Workload**. This [workload](/reference/workload) allows for review and testing of the application before being promoted to upstream [workloads](/reference/workload). The deployment of the **Review Workload** occurs when a pull request from a feature branch to the `main` branch is opened. The application will only be promoted to the `dev` [workload](/reference/workload) if the pull request is closed and merged.

## Permissions

To control which users have the ability to perform sensitive actions, such as merging a pull request, you can utilize the built-in capabilities of GitHub by creating a custom repository role.

Review these [instructions](https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization) on how to create a role.

## Notes

* The example above demonstrates promoting code across four environments (review and development in one [Org](/reference/org), and staging and production in a separate [Org](/reference/org)). Of course, you can arrange each environment within its own [Org](/reference/org), or mix multiple environments within an [Org](/reference/org) as shown in the example. There is no limit to the number of [Orgs](/reference/org) / environments that can be created. This example can be adapted to suit your unique deployment requirements.
* For more complex applications, each environment's [GVC](/reference/gvc) / [workload](/reference/workload) should be configured with its own:

  * [Domain](/reference/domain)
  * [Pull Secrets](/reference/gvc#pull-secrets)
  * [Environment Variables](/reference/workload#environment-variables)
