Contents
How it works
You create a .github/workflows/deploy.yml file — GitHub automatically runs it on push, PR, or on a schedule. You describe the steps: install dependencies, run tests, deploy.
Workflow file structure
# .github/workflows/deploy.yml
name: Deploy
# When to run
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# What to do
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
Deploying to a server over SSH
If the app on your server runs in Docker, the full path from zero to production is covered in deploying to a VPS.
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/my-app
git pull origin main
npm ci --production
pm2 restart app
Secrets
Passwords and keys live in the repository's Secrets. Settings → Secrets and variables → Actions → New repository secret.
⚠️ Never paste passwords directly into the yml file. Use
${{ secrets.MY_SECRET }}— the value is injected at runtime and is not visible in logs.
Deploying to GitHub Pages
How to set up a Pages site in the first place is in a separate guide. The deploy workflow:
name: Deploy to Pages
on:
push:
branches: [ main ]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
environment:
name: github-pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: './dist'
- uses: actions/deploy-pages@v4
💡 The status of the latest workflow shows up right on the repo page — a green check or red cross next to the commit. If your pipeline builds Docker images, speed it up with BuildKit cache.
Discussion
No comments yet. Be the first.