Home Projects Services Blog Contact
Back to Blog

CI/CD with GitHub Actions: from zero to automatic deploys

Run your tests, build and deployment on every push, with a setup you can copy into your own repo.

TL;DR

CI runs your tests automatically on every push and pull request. CD deploys automatically once those tests pass. GitHub Actions does both from a YAML file in your repo, and it's free for public repositories. You push, the pipeline checks the code, and the server updates itself.

What is CI/CD?

Continuous Integration (CI) means every push is built and tested automatically, so a broken change is caught within minutes instead of at release time. Continuous Deployment (CD) goes one step further: when the tests pass on the main branch, the new version goes to production without anyone running commands by hand.

Companies like Google ship to production many times a day. That only works because every change goes through the same automated checks before it reaches users.

Why GitHub Actions?

If your code already lives on GitHub, Actions is the shortest path. It's free for public repositories and includes a monthly allowance of minutes for private ones. There's nothing extra to host: you add a YAML file under .github/workflows/ and GitHub runs it.

Your first workflow

.github/workflows/test.yml
name: Test & Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
      
      - name: Run tests
        run: |
          python manage.py test
      
      - name: Check code style
        run: |
          pip install flake8
          flake8 . --max-line-length=100

Deploying once the tests pass

.github/workflows/test.yml (continued, same jobs block)
  deploy:
    needs: test  # Only runs if tests pass
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to VPS via SSH
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /home/ubuntu/myapp
            git pull origin main
            docker compose build --no-cache
            docker compose up -d

Keep SSH keys, passwords and API tokens in GitHub Secrets (Settings → Secrets and variables → Actions) and read them with ${{ secrets.NAME }}. Never hardcode them in a workflow file.

What to add next

  1. Coverage reports (coverage.py or pytest-cov)
  2. Push the Docker image to Docker Hub or GitHub Container Registry, and deploy that image instead of building on the server
  3. A Slack or Telegram message when a deployment succeeds or fails
  4. A staging environment that deploys automatically when a PR is merged
  5. An automatic rollback if the health check fails after a deploy

Why it's worth the setup

Once the pipeline is in place, nobody deploys by hand anymore. Every push is tested, every deployment runs the same steps, and most regressions are caught before users see them. The setup is a one-time cost that pays off on every release after it.

Tous les articles Article suivant