CI/CD Meets Orchestration: Gitflow Example using Cloudify and GitHub Actions

In my previous articles, I described Cloudify’s integration with Jenkins, as well as with CircleCI and GitHub Actions. These integrations provide easy access to Cloudify from within some of the most popular CI/CD tools in the market.

In this article, I will demonstrate using Cloudify’s integrations within the context of real-world development work. The demonstration will use GitHub Actions, however the same concepts can be applied to any supported CI/CD platform.

Note: before proceeding, you may want to brush up on Gitflow. A good description can be found here.

You can also watch the demo here:

Example Scenario

In our example scenario, we have a Git repository in which:

What we would like to achieve is the following:

Note: you can find the example scenario and repository on GitHub.


First, we will set up our GitHub repository with a few secrets, which will contain general information about our Cloudify environment. In GitHub, click Settings and then Secrets to get to the Secrets screen. Then add the following secrets:

Writing the GitHub Workflows

We will write two GitHub workflows:

(Both files should exist in .github/workflows, as per GitHub’s conventions)

Let’s look at feature.yml:

Note the on -> push -> branches directive, instructing GitHub to run this workflow whenever there’s a push to any branch that adheres to the feature/* name mask.

Next, let’s look at integration.yml:

The algorithm, in high level:

Let’s Go

OK, now let’s give this a try.

We start with a repository containing a simple blueprint, and only one branch: master. The blueprint is:

At this point, develop doesn’t exist yet. Let’s create it and push it to GitHub:

git checkout -b develop
git push -u origin HEAD

This results in the develop branch being created and pushed to GitHub. As this triggers a push event, our integration.yml workflow will fire up:

If we expand the “Install or update deployment” step, we will see that a new deployment was created. That makes sense, as the application didn’t exist; the initial push to develop was meant to create it.

Let’s see Cloudify Manager’s administration console:

Our deployment is there.

Now, let’s create a feature branch off develop, and call it feature/bugfix:

cfy checkout -b feature/bugfix

Now, we’ll change the blueprint by adding a new node template:

Then, we commit and push the feature branch to GitHub:

git add .
git commit -m "Added node template"
git push -u origin HEAD

Since we pushed to a branch of the pattern feature/*, the push will trigger the feature.yml workflow. This workflow creates a new deployment on the test tenant, installs the application, potentially runs tests, and then deletes the environment.

Lastly, let’s merge the feature branch into develop, signifying the end of the development of our feature/bugfix feature branch:

git checkout develop
git merge feature/bugfix
git push

As we pushed to develop, this triggers the integration.yml workflow. This time, however, the deployment exists on Cloudify Manager; we expect it to be updated. And indeed:

If we expand the “Install or update deployment” step, we will see that the deployment was indeed updated, and the old blueprint (that is, the blueprint with which the deployment was associated) was deleted:

Checking Cloudify Manager’s administration console…


This article demonstrated the use of Cloudify’s integration with GitHub Actions, for the purpose of:

The blueprint that we used was very simple, as the Cloudify blueprint was not the focus here. In reality, this blueprint can be arbitrarily complex, involving virtual machines, network resources, Kubernetes resources and virtually any resource that can be managed by Cloudify.

Traveller, writer, musician, software architect; not necessarily in that order