Introduction
In the world of DevOps, automation is everything. Continuous Integration and Continuous Deployment (CI/CD) pipelines streamline code changes, ensuring rapid delivery and consistent environments. GitHub Actions, launched by GitHub in 2019, provides a powerful and native way to automate workflows directly from your GitHub repository.
Whether you’re automating tests, building Docker images, or deploying to production, GitHub Actions can do it. In this guide, we’ll build a fully functional pipeline from scratch, using GitHub Actions to handle CI/CD for a sample application.
⚙️ What is GitHub Actions?
GitHub Actions is a CI/CD and automation tool embedded into GitHub. It allows you to:
- Run scripts or jobs automatically based on events (like pushing code or creating a pull request)
- Build, test, and deploy applications in any language
- Leverage GitHub-hosted runners or self-hosted ones
- Use pre-built Actions from the GitHub Marketplace
You define your workflows as YAML files in your repository.
🔧 Setting Up Your First Workflow
Let’s get hands-on.
Step 1: Project Setup
We’ll use a simple Node.js app as an example, but the same logic applies to any language.
Directory structure:
/my-app
├── .github/workflows/ci.yml
├── package.json
└── index.js
Step 2: Create Your Workflow File
Inside .github/workflows/, create a file named ci.yml.
name: CI Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
What this pipeline does:
- Triggers on pushes and pull requests to main
- Runs on an Ubuntu runner
- Checks out code, installs Node.js and dependencies
- Executes tests
🧠 Understanding Key Concepts
1. Triggers (on:)
These define when the workflow runs:
- push and pull_request are most common
- You can also use workflow_dispatch for manual runs
2. Jobs
Each workflow contains one or more jobs, which run independently by default.
jobs:
build:
runs-on: ubuntu-latest
You can define job dependencies with needs: if they need to run in sequence.
3. Steps
Steps are the individual commands or actions inside a job.
steps:
- name: Install dependencies
run: npm install
4. Actions
You can use pre-built or custom actions via:
uses: actions/setup-node@v3
🧪 Adding Test Reporting
Let’s add more depth by saving test reports for later analysis.
Update the test step:
- name: Run tests with coverage
run: |
npm install -g jest
jest --coverage
And optionally upload the report:
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage/
🚢 Adding a Deployment Step
Suppose you want to deploy to a VPS over SSH after successful tests.
Add secrets to GitHub:
You can add this under Settings -> Secrets and variables -> Actions
- SERVER_IP
- SSH_USER
- SSH_KEY (private key)
Deployment step:
- name: Deploy to server
if: success()
run: |
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SERVER_IP }} 'bash ~/deploy.sh'
env:
SSH_KEY: ${{ secrets.SSH_KEY }}
Also, add a step to write the private key:
- name: Set up SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
This securely deploys code to your VPS on every push.
✅ Bonus: Manual Triggers and Environment Approval
Use workflow_dispatch for manual triggers:
on:
workflow_dispatch:
And define environments with approvals:
jobs:
deploy:
environment:
name: production
url: https://my-app.com
runs-on: ubuntu-latest
🧰 Useful GitHub Actions from the Marketplace
- Upload Artifact: actions/upload-artifact
- Slack Notifications: 8398a7/action-slack
- Docker Build & Push: docker/build-push-action
- Cache Dependencies: actions/cache
🧪 Common CI Patterns
1. Caching Dependencies
Speed up builds with caching:
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
2. Matrix Builds
Test across multiple versions:
strategy:
matrix:
node: [14, 16, 18]
🧱 Best Practices
- Use secret management for sensitive data
- Keep workflows modular using reusable actions
- Add status checks for PRs
- Use caching to reduce execution time
- Limit workflow triggers to necessary branches
🚀 Wrapping Up
GitHub Actions makes CI/CD incredibly accessible, especially for projects hosted on GitHub. With just a few lines of YAML, you can automate code testing, linting, deployments, notifications, and more.
Here’s what we accomplished:
- Built a working CI pipeline
- Installed dependencies and ran tests
- Uploaded test reports
- Deployed to a remote server over SSH
This basic pipeline can scale into a powerful DevOps automation engine as your project grows.
Power Your Projects with vpszen.com VPS Solutions
Looking for reliable hosting to run your Linux servers and host your next big project? VpsZen.com has you covered with top-tier VPS options tailored to your needs.
Choose from ARM64 VPS Servers for energy-efficient performance, or Root VPS Servers for virtual servers with dedicated resources.