Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

chore(infra): add CD pipeline and PM2 ecosystem config - #14

Merged
oduwoleeyinojuoluwa44 merged 6 commits into
devfrom
chore/ci-cd-configuration
May 10, 2026
Merged

chore(infra): add CD pipeline and PM2 ecosystem config#14
oduwoleeyinojuoluwa44 merged 6 commits into
devfrom
chore/ci-cd-configuration

Conversation

@leothatguy

@leothatguy leothatguy commented May 10, 2026

Copy link
Copy Markdown
Contributor

Description

Add CD pipeline and PM2 ecosystem configuration for automated deployments to staging and production environments.

Files added:

  • .github/workflows/cd.yml — CD workflow that SSHs into the server, pulls latest code, writes .env, installs dependencies, builds, runs migrations, and restarts the app via PM2.
  • ecosystem.config.cjs — PM2 process config with environment-specific settings (ports, NODE_ENV) for staging and production.

How it works:

  • Push to staging → deploys to ~/skillbridge/backend/staging on port 5001
  • Push to main → deploys to ~/skillbridge/backend/production on port 4001
  • CI checks (lint, test, build) must pass before deploy runs
  • Environment files are written from GitHub secrets (STAGING_ENV, PRODUCTION_ENV)

Related Issue (Link to Github issue)

N/A — infrastructure setup

Motivation and Context

The project had no automated deployment. Developers had to manually SSH into the server to deploy changes. This CD pipeline automates the full deploy flow (code pull → env setup → build → migrate → restart) and ensures CI passes before any deployment happens.

How Has This Been Tested?

  • YAML syntax validated locally
  • CI workflow verified passing on GitHub Actions
  • Deploy flow designed to be safe on first run (clones repo) and subsequent runs (hard resets to latest)

Screenshots (if appropriate - Postman, etc):

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Summary by CodeRabbit

  • Chores
    • Added automated deployment workflow for staging and production environments.
    • Configured application process management with environment-specific settings.
    • Updated linting configuration to reflect new deployment files.

Review Change Stack

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@leothatguy has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 40 minutes and 59 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e12e0650-0778-435f-a2d8-4e913062f3a2

📥 Commits

Reviewing files that changed from the base of the PR and between 5d69405 and 4cc30fa.

📒 Files selected for processing (2)
  • .github/workflows/cd.yml
  • ecosystem.config.cjs
📝 Walkthrough

Walkthrough

This PR introduces a complete continuous deployment pipeline. It adds a new GitHub Actions CD workflow that triggers on pushes to staging and main, runs the existing CI workflow as a prerequisite, and then deploys via SSH to remote servers using branch-specific environments. A new PM2 ecosystem configuration file defines process management and environment-specific settings. The ESLint configuration is updated to ignore the new PM2 config file.

Changes

Continuous Deployment Pipeline

Layer / File(s) Summary
Process Configuration
ecosystem.config.cjs
PM2 ecosystem config defines a single app (skillbridge-api) running dist/main.js with environment-specific PORT and NODE_ENV for production (5001/production) and staging (4001/staging).
Workflow Trigger & Concurrency
.github/workflows/cd.yml
CD workflow triggers on pushes to staging and main branches with branch-scoped concurrency (cd-${{ github.ref_name }}). Calls reusable CI workflow and defines dependent deploy job.
Deployment Strategy
.github/workflows/cd.yml
Deploy job selects GitHub environment by branch, derives deployment directory and PM2 app name from github.ref_name, and configures SSH connection via appleboy/ssh-action@v1 with secrets.
Remote Deployment Script
.github/workflows/cd.yml
Remote script clones or resets repository, writes .env from branch-specific secret, installs dependencies with pnpm install --frozen-lockfile, builds, runs migrations, and manages PM2 restart with environment flag (production for main, staging for staging branch).
Tooling Updates
eslint.config.mjs
Global ignore list extended to include ecosystem.config.cjs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main changes: adding a CD pipeline and PM2 ecosystem config for infrastructure automation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/ci-cd-configuration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/cd.yml:
- Line 36: The current DOTENV expression uses a brittle A && B || C pattern;
replace it by passing secrets.PRODUCTION_ENV and secrets.STAGING_ENV directly
into the job/env (e.g. export PRODUCTION_ENV, STAGING_ENV, REF_NAME) and add a
small script step (e.g. in the "Deploy via SSH" step or a pre-step) that sets
DOTENV based on REF_NAME (if REF_NAME == "main" use PRODUCTION_ENV else
STAGING_ENV) and immediately fails if DOTENV is empty. Ensure you reference
DOTENV, PRODUCTION_ENV, STAGING_ENV and REF_NAME in that step and write an
explicit non-empty check that exits with an error message when the chosen secret
is missing.
- Around line 46-59: The workflow fails on first deploy because the script runs
cd "$DEPLOY_DIR" before the directory exists; modify the sequence around
DEPLOY_DIR so you create the directory first (e.g., mkdir -p "$DEPLOY_DIR" or
check [ -d "$DEPLOY_DIR" ] and create it if missing) and only then cd into it,
then perform the existing git logic (the if block that checks for .git and runs
git clone --branch "$BRANCH" "$REPO" . or the fetch/reset path); ensure the
sequence around DEPLOY_DIR, cd "$DEPLOY_DIR", and the git clone --branch
"$BRANCH" "$REPO" . lines is reordered so clone is reachable on first run and
consider guarding the clone path against non-empty targets if needed.
- Around line 61-62: The .env file is written from the DOTENV variable using
printf and may be group/world readable; tighten permissions by ensuring umask is
set to 077 before writing or by immediately applying restrictive permissions
after writing (e.g., chmod 600 .env). Update the step that runs printf '%s\n'
"$DOTENV" > .env to either prefix it with a secure umask or follow it with a
chmod to ensure .env is only owner-readable.
- Line 14: Add a new reusable workflow file named ci.yml under .github/workflows
that declares on: workflow_call so the existing uses: ./.github/workflows/ci.yml
reference in the CD workflow resolves; inside ci.yml define the
inputs/permissions/jobs the CD workflow expects (match any expected
inputs/outputs and required permissions/secrets) and ensure the file is a valid
GitHub Actions workflow so the reusable call can execute successfully.
- Around line 76-81: Modify the pm2 restart invocation so it targets the
specific app name and updates environment variables: when checking and
restarting the process, call pm2 restart with the app scope "$APP_NAME" and
include the --update-env flag (i.e., use pm2 restart "$APP_NAME" --update-env or
pm2 restart ecosystem.config.cjs --env "$ENV_FLAG" "$APP_NAME" --update-env
depending on how the ecosystem is referenced) so env_production/env_staging
changes are loaded; keep the existing pm2 start behavior for the else branch and
retain pm2 save after the restart/start.

In `@ecosystem.config.cjs`:
- Around line 11-18: The env_production and env_staging blocks currently default
PORT to 5001/4001 which conflicts with the PR docs; update the PORT fallback in
the ecosystem config (env_production and env_staging) to match the documented
contract (use process.env.PORT || 3003 for env_production and process.env.PORT
|| 3004 for env_staging) or remove the fallback entirely so PORT is read
directly from process.env and missing values fail loudly; ensure NODE_ENV values
remain unchanged.
- Around line 4-9: Add explicit PM2 logging and graceful shutdown settings to
the process config: update the process block that defines name, script,
instances, exec_mode, autorestart, max_memory_restart to also set out_file and
error_file (or a combined file via merge_logs), enable merge_logs, set a
readable log_date_format, and increase kill_timeout to a safe value (e.g.,
several seconds) so Nest HTTP/DB connections can drain gracefully during
restarts; ensure these new properties are present alongside the existing keys
(name, script, instances, exec_mode, autorestart, max_memory_restart).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 11ee6da9-42a2-41ec-91a0-c4a9c7c1dc42

📥 Commits

Reviewing files that changed from the base of the PR and between 962952b and 5d69405.

📒 Files selected for processing (3)
  • .github/workflows/cd.yml
  • ecosystem.config.cjs
  • eslint.config.mjs

Comment thread .github/workflows/cd.yml
jobs:
ci:
name: CI Checks
uses: ./.github/workflows/ci.yml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm ci.yml exists on this branch and declares workflow_call.
fd -t f 'ci\.yml$' .github/workflows
echo '---'
fd -t f 'ci\.yml$' .github/workflows --exec sh -c 'echo "== {} =="; cat {}'

Repository: hngprojects/skillbridge-be

Length of output: 74


🏁 Script executed:

#!/bin/bash
# List all files in .github/workflows/
echo "=== Files in .github/workflows/ ==="
git ls-files .github/workflows/ | sort

echo ""
echo "=== Content of cd.yml around line 14 ==="
sed -n '10,20p' .github/workflows/cd.yml

Repository: hngprojects/skillbridge-be

Length of output: 417


Create .github/workflows/ci.yml with workflow_call trigger.

The reusable workflow referenced at line 14 does not exist in the repository. The uses: ./.github/workflows/ci.yml call will fail at runtime, blocking every deploy. Create ci.yml in .github/workflows/ and declare on: workflow_call: to enable this job to execute.

🧰 Tools
🪛 actionlint (1.7.12)

[error] 14-14: could not read reusable workflow file for "./.github/workflows/ci.yml": open /home/jailuser/git/.github/workflows/ci.yml: no such file or directory

(workflow-call)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/cd.yml at line 14, Add a new reusable workflow file named
ci.yml under .github/workflows that declares on: workflow_call so the existing
uses: ./.github/workflows/ci.yml reference in the CD workflow resolves; inside
ci.yml define the inputs/permissions/jobs the CD workflow expects (match any
expected inputs/outputs and required permissions/secrets) and ensure the file is
a valid GitHub Actions workflow so the reusable call can execute successfully.

Comment thread .github/workflows/cd.yml Outdated
Comment thread .github/workflows/cd.yml
Comment thread .github/workflows/cd.yml
Comment thread .github/workflows/cd.yml
Comment thread ecosystem.config.cjs
Comment thread ecosystem.config.cjs
@oduwoleeyinojuoluwa44
oduwoleeyinojuoluwa44 merged commit 6b4a18b into dev May 10, 2026
2 checks passed
kenneropia pushed a commit that referenced this pull request May 11, 2026
chore(infra): add CD pipeline and PM2 ecosystem config
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants