You repeat the same manual steps with every release. Pull the code, run tests by hand, copy files to the server, restart the service. Miss one step and production breaks. A ci cd pipeline exists to end exactly this pain.In this post we build a pipeline from scratch with GitHub Actions. We cover the build, test, and automated server deploy stages one by one. By the end you will have a setup where every push tests itself and ships to production on its own.
What is a CI CD Pipeline and why does it matter?
CI/CD combines two ideas. Continuous integration means merging code often and testing it automatically on every merge. Continuous deployment means sending tested code to its target environment automatically.A ci cd pipeline joins these two processes into a single flow. The same steps run in the same order on every push to the repository. Human error drops and feedback speeds up. A bug gets caught in the test stage before it ever reaches production.The biggest problem with manual deployment is inconsistency. One day you do the steps right, the next you skip one. Automation removes that inconsistency. The process runs the same way every single time.
The three core stages of the pipeline
A good flow usually has three main stages. Each stage depends on the success of the one before it. If tests fail, deployment never even starts.
StageJobTypical time
Build | Installs dependencies and compiles the app | 1-3 minutes
Test | Runs unit and integration tests | 2-5 minutes
Deploy | Ships verified code to the server | 1-2 minutes
The build stage prepares the environment. It installs dependencies and compiles the code if needed. Using a cache here cuts the time down sharply. Downloading the same dependencies every run is wasted effort.The test stage guards quality. Unit tests, integration tests, and security scans run here. If a test fails, the pipeline stops and warns you right away.
First setup with GitHub Actions
GitHub Actions runs from a YAML file inside your repository. You place the file in the .github/workflows/ folder. The official GitHub Actions documentation explains every option in detail.The example below defines the build and test stages for a Node.js project:
name: ci cd pipeline
on:
push:
branches: [main]
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm testThis file triggers on every push to the main branch. It checks out the code, then sets up the Node environment. The cache: npm line caches dependencies. npm ci runs a clean install and npm test runs the tests.Pay attention to pinning action versions. Above we used tags like @v4. Some teams pin these to a full commit hash for security. That way the code behind an action cannot change without your knowledge.
Adding automated server deploy
Once tests pass, deployment is next. Defining deploy as a separate job is a good habit. This job depends on the build-test job and runs only if that one succeeds.
deploy:
needs: build-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/app
git pull
npm ci --production
sudo systemctl restart appHere the needs: build-test line sets up the dependency. The server details live in repository secrets. Never write an SSH key or password directly into the YAML. Always pass sensitive data through secrets.The script block holds the commands that run on the server. It pulls the code, installs dependencies, and restarts the service. This flow is more than enough for small and mid-sized projects.
Tips to keep the pipeline healthy
A working pipeline can grow slow or fragile over time. The habits below keep it healthy.
- Keep build time under ten minutes. Fast feedback boosts productivity.
- Run independent tests in parallel. A matrix setup shortens total time.
- Scan dependencies automatically with Dependabot or a similar tool.
- Grant job permissions on the least privilege principle.
- Send the team a notification when an important stage fails.
Another key point is a rollback plan. If a deployment breaks, you must be able to return to the previous version. Tagging the last working release makes this easy. When trouble hits, you roll back in minutes.
Moving to production
A CI CD Pipeline reaches full value only with a reliable target server. The place your automated deploy lands must be stable. Guaranteed CPU, RAM, and fast disks make deployment times predictable.At Kritm Cloud Solutions we build custom software and provide the cloud and VPS infrastructure that serves as the deploy target for these pipelines. Review our Turkey-based servers on the services page, or get in touch for setup help.In short, a CI CD Pipeline turns manual steps into reliable automation. Start with the build and test stages, then add automated server deploy. Try it on a small project, and once the flow settles, move it to larger ones. In the end, every push ships safely.
