Drone CI’s rollback mechanism is less about a magical "undo" button and more about strategically redeploying a known good version of your application. It hinges on the immutability of container images and the ability to point your deployment at a specific tag.
Imagine you just pushed a new container image for your web app, tagged my-app:v1.2.0, and Drone CI successfully deployed it. A few hours later, users are reporting critical bugs. You need to revert to the previous stable version, say my-app:v1.1.0. Drone CI itself doesn’t store historical deployments in a way you can "click and revert." Instead, you trigger a new build that explicitly tells your deployment system to use the old image tag.
Here’s how you’d typically orchestrate this, assuming your Drone CI pipeline deploys to Kubernetes using kubectl or a similar tool:
First, identify the exact tag of the last known good build. This will usually be visible in your container registry (e.g., Docker Hub, Quay.io, Google Container Registry). Let’s assume the good tag is my-registry/my-app:v1.1.0.
Next, you need to create a new Drone CI pipeline configuration that overrides the current image tag. You can achieve this by creating a new .drone.yml file (or modifying an existing one for a temporary override) that specifically targets the old image.
Consider a simple Kubernetes deployment manifest. Traditionally, it might look something like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-registry/my-app:v1.2.0 # <-- This is what we want to change
ports:
- containerPort: 80
To roll back, you’d create a new Drone CI pipeline that effectively applies an updated manifest. A common pattern is to use kubectl set image.
In your .drone.yml, you might have a deploy stage like this:
kind: pipeline
type: kubernetes
name: default
steps:
- name: build
image: plugins/docker
settings:
repo: my-registry/my-app
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8} # Example: tag with short commit hash
- name: deploy
image: plugins/kubernetes
settings:
kubeconfig: |
<your-kubeconfig-content>
namespace: default
spec:
# This part would typically apply a manifest file
# For rollback, we'll use kubectl set image
manifest: |-
# Your initial deployment manifest here
# ...
To trigger a rollback, you’d create a new commit with a modified .drone.yml (or trigger a manual build with overridden parameters). The simplest way is to have a dedicated rollback pipeline or a conditional step.
Let’s illustrate a rollback step that uses kubectl set image. You could add this to your .drone.yml:
kind: pipeline
type: kubernetes
name: default
steps:
# ... build step ...
- name: deploy_rollback
image: appleboy/kubectl:1.20.1 # A common kubectl image
settings:
kubeconfig: |
<your-kubeconfig-content>
command: set
args:
- image
- deployment/my-app-deployment # The name of your deployment
- my-app-container=my-registry/my-app:v1.1.0 # The container name and the OLD image tag
when:
environment: rollback # Trigger this manually or via a specific branch/tag
When you trigger a build for the rollback environment, this step will execute kubectl set image deployment/my-app-deployment my-app-container=my-registry/my-app:v1.1.0. This command tells Kubernetes to update the my-app-deployment to use the my-registry/my-app:v1.1.0 image for its my-app-container. Kubernetes then performs a rolling update, gradually replacing the old pods with new ones running the older image.
The key is that your deployment tool (Kubernetes in this case) manages the actual rollout. Drone CI is simply the orchestrator that tells the deployment tool what to deploy. By creating a new build that specifies the old image tag, you’re effectively instructing your infrastructure to revert.
Another approach, if you’re managing your Kubernetes manifests with tools like Helm or Kustomize, is to update your values.yaml or kustomization.yaml to point to the previous image tag and then trigger a new Drone CI build that applies these updated configuration files. For example, with Kustomize, you might change your kustomization.yaml to:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml # Your base deployment
images:
- name: my-registry/my-app
newName: my-registry/my-app
newTag: v1.1.0 # <-- Changed from v1.2.0 to v1.1.0
Then, your Drone CI pipeline would run kustomize build . | kubectl apply -f - targeting this modified configuration.
The underlying principle for all these methods is that containers are immutable. You don’t "roll back" the running container; you instruct your orchestrator to replace the current set of containers with new ones that are built from a different, older image tag. Drone CI’s role is to provide the trigger and the environment for these commands to be executed.
If you’ve successfully rolled back to v1.1.0 and then later try to deploy v1.2.0 again, you might find your CI pipeline failing to build v1.2.0 if the previous deployment of v1.2.0 was removed from your registry, or if there are caching issues in your build process.