May 16, 2025
Don’t read this
Unless you’ve read this article on mastering CI — otherwise you’ll miss the foundation of what Continuous Delivery truly relies on.
Continuous Delivery (CD) isn’t magic. It’s the final step in a pipeline that must begin with a healthy CI setup and strong code review culture. Trusting CD to ship to production means you’ve automated everything before that: tests, builds, and verification. Here’s a complete, working example of how you can get there with Ruby on Rails — and deploy confidently across 4 major platforms.
Want to Incorporate CI/CD into Your Project?
Whether you’re deploying to AWS, DigitalOcean, GCP, or Heroku — integrating CI/CD will transform the way you ship code:
Automate tests and deployments
Catch bugs early and reduce downtime
Deploy confidently with every merge
Focus on features, not firefighting
Let’s get your CI/CD pipeline running smoothly — with GitHub Actions, GitLab CI/CD, Jenkins, CircleCI, or Bitbucket Pipelines.
Get in touch — and let’s automate your deployments the right way.
Continuous Delivery: What It Is and Why It Needs Trust
Continuous Delivery (CD) automates code deployment to production — but automation without trust is a trap. To trust CD, you need:
-
Well-tested CI pipelines
-
Reliable code review policies (no direct push to main!)
-
Secure secrets management
-
Predictable build and release steps
CD doesn’t replace human quality — it enforces quality you’ve already validated.
Goal: Real-World CD Across 5 Platforms and 4 Clouds
We’ll configure a real Ruby on Rails (or any web app) project to:
- Build and test code with each CI platform
- Deploy automatically to:
Each section includes a complete example, ready to adapt.
Requirements (Common Setup)
Across all providers:
-
Dockerfile in your repo
-
.env.production or ENV variables managed in cloud dashboard
-
CI triggers on main branch or a release-* tag
FROM ruby:3.2
WORKDIR /app
COPY . .
RUN bundle install
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
GitHub Actions CD Setup
Add a deploy job after your test job:
# .github/workflows/deploy.yml
name: Deploy to GCP
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Auth to GCP
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Deploy to Cloud Run
uses: google-github-actions/deploy-cloudrun@v2
with:
service: my-rails-app
image: gcr.io/my-project/my-rails-app
You can swap the deploy step to match AWS , Heroku , or DigitalOcean using their respective CLIs.
GitLab CI/CD Setup
GitLab has first-class CD support — just add a deploy stage:
stages:
- test
- deploy
deploy_production:
stage: deploy
script:
- echo "$GCLOUD_KEY" > key.json
- gcloud auth activate-service-account --key-file=key.json
- gcloud config set project $GCP_PROJECT
- gcloud builds submit --tag gcr.io/$GCP_PROJECT/rails-app
- gcloud run deploy rails-app --image gcr.io/$GCP_PROJECT/rails-app --region us-central1
only:
- main
For AWS , you can replace this with aws s3 cp or eb deploy, and for Heroku , use heroku container:release.
Jenkins CD Setup
In Jenkinsfile, add a deploy stage:
pipeline {
agent any
environment {
AWS_ACCESS_KEY_ID = credentials('aws-access')
AWS_SECRET_ACCESS_KEY = credentials('aws-secret')
}
stages {
stage('Test') {
steps {
sh 'bundle install'
sh 'bundle exec rspec'
}
}
stage('Deploy to AWS') {
steps {
sh 'docker build -t my-rails-app .'
sh 'aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.region.amazonaws.com'
sh 'docker tag my-rails-app:latest $ECR_URL:latest'
sh 'docker push $ECR_URL:latest'
sh 'ecs deploy command or CodeDeploy CLI here...'
}
}
}
}
Jenkins shines with infrastructure-heavy, flexible builds — but can be tricky to scale for team collaboration compared to GitHub or GitLab.
CircleCI CD Setup
Use workflows: to chain build and deploy:
# .circleci/config.yml
jobs:
build:
...
deploy:
docker:
- image: cimg/base:stable
steps:
- checkout
- run: |
echo "$HEROKU_API_KEY" | docker login --username=_ --password-stdin registry.heroku.com
docker build -t registry.heroku.com/$HEROKU_APP_NAME/web .
docker push registry.heroku.com/$HEROKU_APP_NAME/web
heroku container:release web --app $HEROKU_APP_NAME
workflows:
version: 2
build_and_deploy:
jobs:
- build
- deploy:
requires:
- build
You can replace the deploy script to target GCP , AWS , or DigitalOcean as needed.
Bitbucket Pipelines CD Setup
pipelines:
branches:
main:
- step:
name: Deploy to DigitalOcean
image: ruby:3.2
script:
- apt-get update && apt-get install -y curl
- curl -sL https://repos.digitalocean.com/install.sh | bash
- doctl auth init -t $DIGITALOCEAN_TOKEN
- doctl apps create-deployment $APP_ID
You can also deploy to Heroku or AWS by installing their CLIs inside the image.
CD Cloud Target Summary
Security & Trust in CD
- Only deploy after CI passes
- Only deploy code reviewed and merged to main
- Use GitHub/GitLab protected branches or review rules
- Keep secrets encrypted or managed in vaults
“CD is not about speed. It’s about confidence.”
Final Takeaways
- You must trust your CI to make CD reliable.
- Each platform — GitHub, GitLab, Jenkins, CircleCI, Bitbucket — can support real-world CD if your tests and workflows are clean.
- Cloud targets like AWS, GCP, Heroku, and DigitalOcean each have strengths. Choose based on your app’s infra needs.
- CI + Code Reviews + Atomic Deploys = Sanity.
Top comments (0)