Skip to content

darestack/github-actions-ec2-pipeline

Repository files navigation

github-actions-ec2-pipeline

GitHub Actions pipeline that builds, tests, and deploys a Node.js app to AWS EC2 with PM2 reload, rollback support, and scheduled health checks.

CI Pipeline


Pipeline Overview

Push to main / feature branch
  │
  └── ci.yml
        └── build-and-test: Node 22/24 matrix → npm ci → Jest tests → ESLint gate
                │
                └── release.yml (manual dispatch or pushed v* tag)
                      ├── deploy: tar.gz → SCP to EC2 → deploy.sh (PM2 reload, atomic symlink swap)
                      └── create-release: GitHub Release for tagged deploys

Key Design Decisions

Decision Implementation Why
Low-interruption deploy pm2 reload + atomic symlink swap (current -> release-timestamp) Keeps deploy behavior predictable and rollback-friendly
Auto-rollback deploy.sh keeps the previous current target until the new release passes health checks Restores the last known-good symlink if deploy breaks the app
Controlled release trigger release.yml runs from a manual dispatch or pushed v* tag Avoids accidental EC2 deploys from routine CI commits
Health check monitoring Scheduled workflow runs hourly and reuses one open health-check issue while an outage is active Avoids duplicate alert noise and keeps incident state readable
Separate CI / CD workflows ci.yml validates code; release.yml deploys from manual or tag triggers Keeps routine validation separate from EC2 deployment

Workflows

ci.yml — Continuous Integration

Triggers: push to main, development, feature/* branches + all PRs

  1. build-and-test: Node 22/24 matrix → npm ci → Jest test suite → ESLint gate

release.yml — Continuous Deployment

Triggers: manual dispatch or new tag matching v*

  1. deploy: packages build → SCP to EC2 → runs /var/www/app/scripts/deploy.sh
    • Installs dependencies in release dir → atomic symlink currentpm2 reload
    • On failure: restores previous symlink → pm2 reload (auto-rollback)
  2. create-release: publishes GitHub Release with tag name

health-check.yml — Uptime Monitoring

Runs hourly. Hits /api/health for configured environments. If a check fails, the workflow creates one health-check issue or comments on the existing open issue instead of creating duplicates.


Required GitHub Secrets

Secret Purpose
PROD_EC2_HOST Production EC2 hostname or IP
PROD_EC2_USER SSH username
PROD_EC2_KEY Private SSH key (PEM format)

Also set: Actions → General → Workflow permissions → Read and write (allows built-in token to create releases and issues).


Application Stack

Node.js 22/24 · Express · Jest · PM2 · GitHub Actions · AWS EC2

The EC2 host should run Node.js 22 or 24 so the deployed runtime matches CI.


Local Setup

git clone https://github.com/darestack/github-actions-ec2-pipeline.git
cd github-actions-ec2-pipeline
npm install
npm test
npm start
# → http://localhost:3000
# → http://localhost:3000/api/health

To add Nginx as a reverse proxy on the EC2 instance (port 80 → 3000):

server {
    listen 80;
    server_name _;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

About

GitHub Actions pipeline for a Node/Express app: Node 22/24 CI, controlled manual/tag deploy to EC2 via SSH/PM2, atomic-symlink rollback, and health checks.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors