Rolling Deployments
Objective
Create a service deployment that automatically updates with a newly built image for each commit pushed to your git repository.
Prerequisites
Complete: CI / CD Getting Started Guide
This guide assumes that you already have application code and a corresponding Dockerfile committed and pushed to your version control system.
Background
A common practice in software development is to have an environment such as development
that is running the latest code on the primary integration branch of your git repository (e.g., main
). We will demonstrate how to easily accomplish this using the Panfactum CI / CD system.
In the below walkthrough, we will be referencing the module that deploys this website as an example. This is for reference only. You will not have access to the private website images used by this module, so you must create your own application code and IaC; you cannot simply copy our modules.
Build and Push Image from Dockerfile
First, you need to build and push an image based on the Dockerfile in your repository. We provide a submodule that will create a WorkflowTemplate that does this for you: wf_dockerfile_build.
Add this submodule to your CI / CD module that you created in the Getting Started guide. As an example of how this might look, you can reference our CI / CD module for this website.
Note that the images generated by the Workflow are tagged with the commit hash that was checked out for the build.
Before proceeding, ensure you have used the WorkflowTemplate to successfully create a build of your repo’s Dockerfile.
Deploy the Image
Next, you must deploy your image using IaC. We provide an example of our website service as well as the terragrunt.hcl
that we use to deploy it.
Notice that our module has an input called website_image_version
which is set in terragrunt.hcl
as follows:
website_image_version = run_cmd("--terragrunt-quiet", "pf-get-commit-hash", "--ref=main", "--repo=https://github.com/panfactum/stack")
The run_cmd function is a Terragrunt feature that allows you to call an external command as your Terragrunt code is evaluated. The stdout from this call is then returned by the function.
We provide a command in the devShell called pf-get-commit-hash
that takes a git reference and a repository URL and returns the commit hash that reference points to. By choosing main
, our module will deploy the image corresponding to the latest commit on the main
branch.
Before proceeding, ensure you can successfully deploy and run your service. Commit and push this new IaC so that we can pull it in the Workflows we create in the following step.
Combine WorkflowTemplates
Next, we must create a WorkflowTemplate the combines both the wf_dockerfile_build
logic and the wf_tf_deploy
logic (created in the Getting Started guide). This new WorkflowTemplate will reuse the existing WorkflowTemplates to first build the image and then deploy it.
This composition pattern is described in our guide for triggering Workflow. The full code for our website example can be found here, but the following snippets deserve an explanation:
Snippet 1
This code combines templates from the WorkflowTemplates created by the wf_dockerfile_build
and wf_tf_deploy
submodules and then runs them in sequence. The entrypoint
output of each submodule refer to the name of the entry / root template of that WorkflowTemplate. 1
templates = [ { name = "entry", dag = { tasks = [ { name = "build-image" templateRef = { name = module.website_builder.name template = module.website_builder.entrypoint } }, { name = "deploy-image" templateRef = { name = module.tf_deploy.name template = module.tf_deploy.entrypoint } depends = "build-image" } ] } }]
Snippet 2
This code passes the git_ref
and tf_apply_dir
parameters to each reference template. For this Workflow, we want to build from the main
branch and then apply only the pf_website
module.
passthrough_parameters = [ { name = "git_ref" value = "main" }, { name = "tf_apply_dir" value = "packages/reference/environments/production/us-east-2/pf_website" }]
Once you have created an analogous WorkflowTemplate in your IaC, deploy it. You should now see it in the Argo web dashboard. If you create a new Workflow from the WorkflowTemplate, it should successfully run a combined execution graph of both the build and deploy Workflow:

Connect to CI / CD Webhooks
Finally, you can now connect this new WorkflowTemplate to the Argo Sensor for your CI / CD pipeline. This will allow you to trigger a new Workflow from this WorkflowTemplate whenever you push to main
(or whichever branch you want to use to automatically trigger deployments).
Here is an example of how we do this for our website.