Automate Your Workflow with GitHub Actions
Learn how to automate builds, tests, and deployments with GitHub Actions, streamlining your dev workflow from commit to production.
If you’re still manually deploying code, running tests on your laptop, or SSH-ing into servers to pull changes, you’re wasting time. GitHub Actions lets you automate the entire pipeline—from commit to production—directly from your repository. Here’s how to set up a practical workflow that actually saves you hours each week.
The Basics: Your First Workflow File
GitHub Actions lives in .github/workflows/ as YAML files. Every push, pull request, or schedule can trigger a workflow. Start with a simple one that runs tests on every push:
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
Save this as .github/workflows/ci.yml. That’s it—your tests now run automatically on every commit. No more “works on my machine.”
Automating Deployment with SSH
The most common real-world use case: deploy to your own VPS or shared hosting. Instead of manual SSH commands, let the workflow handle it. Here’s a deployment job that runs after tests pass:
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/mysite
git pull origin main
composer install --no-dev
sudo systemctl reload nginx
Store SERVER_HOST, SERVER_USER, and SSH_PRIVATE_KEY in your repository settings under Settings → Secrets and variables → Actions. Never hardcode credentials in the YAML file.
Conditional Triggers: Don’t Waste Resources
Running everything on every push is wasteful. Use path filters to run only what’s needed:
name: Deploy WordPress Plugin
on:
push:
branches: [main]
paths:
- 'plugin/**'
- '!plugin/readme.txt' # skip docs-only changes
workflow_dispatch: # manual trigger
For scheduled tasks—like nightly backups or database cleanups—use cron syntax:
on:
schedule:
- cron: '0 3 * * *' # every day at 3 AM
Reusable Workflows and Caching
Don’t repeat yourself across multiple projects. Create a reusable workflow in a central repo:
# .github/workflows/deploy.yml (in your shared repo)
on:
workflow_call:
inputs:
environment:
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to ${{ inputs.environment }}"
Then call it from any other repo:
jobs:
deploy-prod:
uses: yourorg/shared-workflows/.github/workflows/deploy.yml@main
with:
environment: production
Also cache dependencies to speed things up:
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
Conclusion
GitHub Actions turns your repository into a CI/CD server with zero infrastructure costs. Start with one workflow—automate your tests first, then add deployment. Check the Actions tab after each push to see logs and fix failures. Within a week, you’ll wonder how you ever deployed manually. The key is to start small and iterate.