What CI/CD is and why teams suffer without it
Imagine this: a developer pushes changes, passes the code to someone else who checks it on their machine, says “it works,” and the code goes to production. In the morning, users cannot log in. Familiar?
CI (Continuous Integration) fixes the first part: every commit is automatically tested and built. No need to wait for someone to manually check.
CD (Continuous Delivery / Deployment) automates the rest: if tests pass, the code is automatically ready for deployment (Delivery) or even deploys itself (Deployment).
Problems without CI/CD
- Errors are found late. A commit was made yesterday, the error is found today, already on top of 5 other commits.
- “It works on my machine” doesn’t scale. Local environment differs from the server.
- Deployment is stressful. When releases are done manually once a month, it is always scary and failures are inevitable.
- The team waits. Without automation, someone has to wait for someone else to run tests or cut a release.
How a pipeline works
A pipeline is a chain of steps:
- Push — someone pushes code to the repository.
- Test — tests run automatically. If they fail — the pipeline stops.
- Build — the code is compiled, bundled, or packaged into a Docker image.
- Deploy to staging — verification on a test server.
- Deploy to production — the final rollout (manual or automatic).
Each step must pass before the next starts. It is like an assembly line: if a part is defective, the line stops.
CI and CD are not the same thing
CI (Continuous Integration)
Automatically tests code after a commit. This is the foundation. Without CI, no CD makes sense.
Continuous Delivery
Code goes through CI and is automatically prepared for deployment. The final step — a “Deploy” button — is pressed manually. Good for most teams.
Continuous Deployment
Same thing, but without the button: every successful commit goes to production automatically. Requires high confidence in tests and monitoring.
Where to start
Level 1: automated tests
The simplest starting point. Add test execution after every push. If tests fail — the developer knows immediately.
# GitHub Actions
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
Level 2: build
Add a build step after tests pass:
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
Level 3: staging deploy
After a successful build — deploy to staging:
deploy-staging:
needs: build
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh staging
Level 4: production deploy
Manual or automatic production deployment:
deploy-prod:
needs: deploy-staging
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh production
Common mistakes
1. Starting with CD without CI
Without tests, automated deployment is a roulette game. Tests first.
2. Long pipelines without feedback
If a pipeline takes 40 minutes, the developer disconnects and will not see the result quickly. Keep fast feedback: tests under 5–10 minutes, builds under 10.
3. Ignoring CI failures
When CI fails and the team gets used to ignoring it — CI becomes useless. Better to have 5 tests that always run than 500 that everyone ignores.
4. Overusing Continuous Deployment
If tests only cover 10% of the code — automatic production deployment is risky. Delivery (with a button) is better for most teams.
Conclusion / action plan
CI/CD is not about technology. It is about trust. When you trust your tests and processes, deployment stops being a scary event.
Here is what to do next:
- Add automatic test runs after every commit.
- Make sure developers can see CI results (green / red).
- Automate builds after tests pass.
- Try a staging deploy as the next step.
- Once the team is comfortable — add production deploy (with a button or automatically).
You do not need to implement everything at once. Start with tests and build up gradually.