{"id":18834568,"url":"https://github.com/controlplane-com/environment-promotion-example","last_synced_at":"2025-10-24T14:46:16.837Z","repository":{"id":43464524,"uuid":"463689215","full_name":"controlplane-com/environment-promotion-example","owner":"controlplane-com","description":null,"archived":false,"fork":false,"pushed_at":"2024-03-27T22:31:11.000Z","size":31,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-12-30T07:42:28.485Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/controlplane-com.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-25T22:11:38.000Z","updated_at":"2022-02-25T22:15:18.000Z","dependencies_parsed_at":"2024-12-31T14:02:05.969Z","dependency_job_id":null,"html_url":"https://github.com/controlplane-com/environment-promotion-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/controlplane-com%2Fenvironment-promotion-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/controlplane-com%2Fenvironment-promotion-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/controlplane-com%2Fenvironment-promotion-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/controlplane-com%2Fenvironment-promotion-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/controlplane-com","download_url":"https://codeload.github.com/controlplane-com/environment-promotion-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239768923,"owners_count":19693764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T02:13:17.402Z","updated_at":"2025-10-24T14:46:16.735Z","avatar_url":"https://github.com/controlplane-com.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Control Plane - Environment Promotion Example\n\nThis example demonstrates the promotion of an application to downstream environments (development -\u003e production) using\nControl Plane and GitHub Actions. As part of the promotion process, a `Staging Workload` is deployed to test\nupdates before promoting to production.\n\nThe current repository contains a Node.js application with two branches, `dev` and `main`. These branches correspond to `dev` and `prod` Control Plane Orgs, respectively.\n\nDuring the promotion process, the image built for development is used by the production environment and does not need to be rebuilt. This is a great time saver for lengthy build processes.\n\nThis example demonstrates the promotion between two environments - dev, main. There is no limit to the number of Orgs / environments that can be used. The example can be extended to your own unique deployment requirements.\n\n## GitHub Actions\n\nThis project contains three GitHub Actions (in the `./.github/workflows` directory) that perform the following:\n\n1. On a push to the `dev` branch, the application is containerized and pushed to the dev Org's private repository.\n   The GVC and Workload is updated (or created if it doesn't exists) by applying the YAML contents of the files `./cpln/cpln-gvc.yaml` and `./cpln/cpln-workload.yaml`.\n2. When a pull request is opened to merge the code to the `main` branch, a `staging` workload is\n   updated (or created if it doesn't exists) in the same dev Org by applying the same files as step 1, except that the workload name is prefixed with `staging`. This allows the application to be reviewed and tested before being pushed to the production Org. Note that the same org is used in this case, but it could easily be factored to use one org per environement.\n3. Once the pull request is accepted and the code is merged to the `main` branch, the GVC and Workload in the production Org\n   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 files is that the `prod` version contains the `Pull Secret` that is needed the pull the image from the dev Org. The Workload uses the image pushed earlier to the development Org.\n\n## Control Plane Prerequisites\n\nThe following Control Plane resources are required:\n\n- Two Control Plane Orgs representing a `dev` and `prod` environment.\n\n## Control Plane Authentication Set Up\n\nThis example uses the Control Plane CLI to perform the necessary actions within the GitHub Actions. The CLI requires a `Service Account` with the proper permissions to perform actions against the Control Plane API.\n\nSince actions will be performed against multiple Orgs, a `Service Account` is required in each Org.\n\n**Perform the following steps in each Org:**\n\n1. Follow the Control Plane documentation to create a `Service Account` and create a key. Take a note of the key. It will be used in the next section.\n2. Add the Service Account to the `superusers` group. Once the GitHub Action executes as expected, a policy can be created with a limited set of permissions and the `Service Account` can be removed from the `superusers` group.\n\n## Example Set Up\n\n**Perform the following steps to set up the example:**\n\n1. Fork the example into your own workspace.\n\n2. The following variables are required and must be added as GitHub repository secrets.\n\n```\nBrowse to the Secrets page by clicking `Settings` (top menu bar), then `Secrets` (left menu bar), and finally click `Actions`.\n```\n\nAdd the following variables:\n\n- `CPLN_ORG_DEVELOPMENT`: Control Plane development Org.\n- `CPLN_ORG_PRODUCTION`: Control Plane production Org.\n- `CPLN_GVC`: The name of the GVC.\n- `CPLN_WORKLOAD`: The name of the Workload.\n- `CPLN_TOKEN_DEVELOPMENT`: Development Org's Service Account Key from the previous step.\n- `CPLN_TOKEN_PRODUCTION`: Production Org's Service Account Key from the previous step.\n- `CPLN_IMAGE`: The name of the image that will be deployed to the development Org's private repository. The GitHub Action workflow will append the short SHA of the commit as the image tag.\n\n3. Review the `.github/workflow/*` files. These actions will be triggered as described in the `GitHub Actions` section above.\n\n4. Review the Control Plane YAML files that are located in the `/cpln` directory. No changes are required to execute the example.\n   - The `cpln-gvc.yaml` file defines the GVC to be created/updated for the `dev` Org.\n   - The `cpln-gvc-prod.yaml` file defines the Pull Secret and GVC to be created/updated for the `prod` Org.\n   - The `cpln-workload.yaml` file defines the Workload to be created/updated corresponding to the dev/staging/prod Workloads.\n\n## Running the App\n\nAfter the GitHub Action has successfully deployed the application, it can be tested by following these steps:\n\n1. Browse to the Control Plane Console (https://console.cpln.io/).\n2. If necessary, select a different Org by clicking your profile circle in the upper right corner, click the Org pull-down, and select the target Org.\n3. Select the GVC that was set in the `CPLN_GVC` variable.\n4. Select the workload that was set in the `CPLN_WORKLOAD` variable. The `staging` Workload will be prefixed with `staging-`.\n5. Click the `Open` button. The app will open in a new tab. The output of the application will be displayed.\n\n## Notes\n\n- The `cpln apply` command creates and updates the resources defined within the YAML file. If the name of a resource is changed, `cpln apply` will create a new resource. Any orphaned resources will need to be manually deleted.\n\n- The Control Plane CLI commands use the `CPLN_ORG` and `CPLN_TOKEN` environment variables when needed. There is no need to add the --org or --token flags when executing CLI commands.\n\n- The GVC definition must exists in its own YAML file. The `cpln apply` command executing the file that contains the GVC definition must be executed before any child definition YAML files (workloads, identities, etc.) are executed.\n\n## Permissions\n\nTo 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.\n\nReview these \u003ca href=\"https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization\" target=\"_blank\"\u003einstructions\u003c/a\u003e on how to create a role.\n\n## Helper Links\n\nGitHub\n\n- \u003ca href=\"https://docs.github.com/en/actions\" target=\"_blank\"\u003eGitHub Actions Docs\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontrolplane-com%2Fenvironment-promotion-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontrolplane-com%2Fenvironment-promotion-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontrolplane-com%2Fenvironment-promotion-example/lists"}