Skip to content

Automation deployment for staging and prod#70

Open
Ayush8923 wants to merge 6 commits intomainfrom
feat/frontend-cicd-deployment
Open

Automation deployment for staging and prod#70
Ayush8923 wants to merge 6 commits intomainfrom
feat/frontend-cicd-deployment

Conversation

@Ayush8923
Copy link
Collaborator

@Ayush8923 Ayush8923 commented Mar 17, 2026

Issue: #22

Summary:

  • Added GitHub Actions workflow to automate frontend deployment on push to main and release branch.
  • Replaced manual EC2 deployment (git pull) with automated SSH-based pipeline

Summary by CodeRabbit

  • Chores
    • Added automated deployment workflows for both staging and production environments.
    • Deployments now remotely update servers, install dependencies, build the frontend, and restart the running app—reducing manual release steps, speeding rollouts, and improving consistency and uptime.

@Ayush8923 Ayush8923 self-assigned this Mar 17, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9d602375-967c-4f89-b89d-92cfd16c6c39

📥 Commits

Reviewing files that changed from the base of the PR and between 8d79917 and e8ca6ee.

📒 Files selected for processing (1)
  • .github/workflows/cd-staging.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/cd-staging.yml

📝 Walkthrough

Walkthrough

Two new GitHub Actions workflows were added to deploy the Kaapi frontend to EC2: staging (triggers on pushes to feat/frontend-cicd-deployment) and production (triggers on pushes to release). Each SSHes to an EC2 host, pulls code, installs deps, builds, and manages the PM2 process.

Changes

Cohort / File(s) Summary
CD Workflows
.github/workflows/cd-staging.yml, .github/workflows/cd-production.yml
Added two deployment workflows. Each checks out the repo, SSHes to an EC2 host using secrets, cds to the configured build directory, pulls the configured branch (main for staging script, release for production), stops the PM2 app (tolerates missing process), runs npm ci and npm run build, then starts the PM2 process.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor GitHubActions as "GitHub Actions"
    participant Runner as "Actions Runner\n(ubuntu-latest)"
    participant EC2 as "EC2 Host"
    participant PM2 as "PM2\n(process manager)"
    GitHubActions->>Runner: trigger on push (feat/frontend-cicd-deployment / release)
    Runner->>EC2: SSH using secrets (host, user, key)
    EC2->>EC2: cd $BUILD_DIRECTORY\ngit pull origin (branch)\nset -e
    EC2->>PM2: pm2 stop $PM2_APP_NAME || true
    EC2->>EC2: npm ci\nnpm run build
    EC2->>PM2: pm2 start $PM2_APP_NAME
    PM2-->>Runner: process started / restarted
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 I hopped to GitHub with keys in paw,
I pulled release and main without a flaw,
PM2 yawned and rose from its den,
Builds ran bright — then I hopped again,
Carrot in hand, I cheered: “Deployed!”

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding GitHub Actions workflows for automated deployment to both staging and production environments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 feat/frontend-cicd-deployment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
.github/workflows/cd-production.yml (1)

13-45: Extract shared staging/production logic into a reusable workflow.

This deployment block is largely duplicated across both workflow files, which increases drift risk and patch latency for fixes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 13 - 45, Deployment steps
using the appleboy/ssh-action@v1.0.3 and the SCRIPT_NAME/pm2/npm sequence are
duplicated; extract this shared SSH deploy logic (the step named "Deploy via
SSH" and its script that uses SCRIPT_NAME, pm2 stop/start, npm ci, npm run
build, git pull) into a reusable workflow (e.g., a workflow called "deploy-ssh"
that exposes inputs like host, user, key, project_path and SCRIPT_NAME and uses
workflow_call), then replace the duplicated blocks in both staging and
production workflows with a single call to that reusable workflow (use the
workflow_call inputs to pass secrets/values). Ensure the reusable workflow
preserves the set -e script behavior and existing environment variable names so
pm2/npm/git commands continue to work unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/cd-production.yml:
- Around line 41-42: Add a pre-build guard that fails the job if the required
build-time env var NEXT_PUBLIC_BACKEND_URL is missing so the pipeline cannot run
npm run build (next build) with an invalid config; implement this by inserting a
step before the "===== Build Application =====" / npm run build step that checks
for NEXT_PUBLIC_BACKEND_URL (exit non‑zero and echo a clear error if unset or
empty) so the workflow fails fast when the variable is absent.
- Around line 32-33: The current deployment uses a non-deterministic "git pull
origin release" which can create merge commits or leave a dirty working tree;
replace that step with an explicit fetch and hard-reset sequence: run "git fetch
--prune origin release", then "git reset --hard origin/release" and optionally
"git clean -fdx" to remove untracked files, ensuring the script enforces an
exact branch state before continuing (replace the "git pull origin release"
invocation).

In @.github/workflows/cd-staging.yml:
- Around line 9-24: The deploy job is not scoped to staging and uses generic
secret names; update the job definition for the deploy job to include an
environment: staging and switch all generic secrets and env refs to
staging-specific secrets (e.g., replace secrets.EC2_HOST, secrets.EC2_USER,
secrets.EC2_SSH_KEY, and secrets.PM2_APP_NAME with secrets.STAGING_EC2_HOST,
secrets.STAGING_EC2_USER, secrets.STAGING_EC2_SSH_KEY,
secrets.STAGING_PM2_APP_NAME) so the appleboy/ssh-action invocation and
SCRIPT_NAME env use staging-only values and cannot target production.
- Around line 35-45: The script currently stops the PM2 process (pm2 stop
"$SCRIPT_NAME") before running npm ci and npm run build, which can leave the
service down if build fails; move the pm2 stop/restart sequence so that npm ci
and npm run build run first and only after they succeed perform the process
restart, and replace the stop + start sequence with pm2 reload "$SCRIPT_NAME"
(or pm2 reload ecosystem file) to achieve a zero-downtime restart; ensure the
commands referencing SCRIPT_NAME and the pm2 invocation are relocated after the
build steps and that failures in npm ci/npm run build do not stop a currently
running instance.
- Around line 18-25: Add SSH host key fingerprint verification to the
appleboy/ssh-action@v1.0.3 invocation by supplying the fingerprint parameter
(use a repository secret like SSH_HOST_FINGERPRINT) alongside the existing with:
host/username/key entries; update the workflow to read the fingerprint from
secrets and pass it into the action so the action performs host key pinning and
prevents MITM attacks during deployments.

---

Nitpick comments:
In @.github/workflows/cd-production.yml:
- Around line 13-45: Deployment steps using the appleboy/ssh-action@v1.0.3 and
the SCRIPT_NAME/pm2/npm sequence are duplicated; extract this shared SSH deploy
logic (the step named "Deploy via SSH" and its script that uses SCRIPT_NAME, pm2
stop/start, npm ci, npm run build, git pull) into a reusable workflow (e.g., a
workflow called "deploy-ssh" that exposes inputs like host, user, key,
project_path and SCRIPT_NAME and uses workflow_call), then replace the
duplicated blocks in both staging and production workflows with a single call to
that reusable workflow (use the workflow_call inputs to pass secrets/values).
Ensure the reusable workflow preserves the set -e script behavior and existing
environment variable names so pm2/npm/git commands continue to work unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 94bb20bf-62eb-4db7-871b-95ae6154fa90

📥 Commits

Reviewing files that changed from the base of the PR and between 1b29e4b and 6c3d49c.

📒 Files selected for processing (2)
  • .github/workflows/cd-production.yml
  • .github/workflows/cd-staging.yml

Comment on lines +32 to +33
echo "===== Fetch Latest Code ====="
git pull origin release
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use deterministic branch sync instead of git pull.

Line 33 can create merge commits or deploy a dirty local state. Deploy scripts should enforce exact branch state.

Deterministic sync example
             echo "===== Fetch Latest Code ====="
-            git pull origin release
+            git fetch --prune origin
+            git checkout -B release origin/release
+            git reset --hard origin/release
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "===== Fetch Latest Code ====="
git pull origin release
echo "===== Fetch Latest Code ====="
git fetch --prune origin
git checkout -B release origin/release
git reset --hard origin/release
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 32 - 33, The current
deployment uses a non-deterministic "git pull origin release" which can create
merge commits or leave a dirty working tree; replace that step with an explicit
fetch and hard-reset sequence: run "git fetch --prune origin release", then "git
reset --hard origin/release" and optionally "git clean -fdx" to remove untracked
files, ensuring the script enforces an exact branch state before continuing
(replace the "git pull origin release" invocation).

Comment on lines +41 to +42
echo "===== Build Application ====="
npm run build
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail fast when required build-time env vars are missing.

Given next build (from package.json scripts) won’t enforce NEXT_PUBLIC_BACKEND_URL, this pipeline can successfully deploy a broken frontend config.

Guard before build
             echo "===== Build Application ====="
+            : "${NEXT_PUBLIC_BACKEND_URL:?NEXT_PUBLIC_BACKEND_URL is required for production build}"
             npm run build
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "===== Build Application ====="
npm run build
echo "===== Build Application ====="
: "${NEXT_PUBLIC_BACKEND_URL:?NEXT_PUBLIC_BACKEND_URL is required for production build}"
npm run build
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 41 - 42, Add a pre-build
guard that fails the job if the required build-time env var
NEXT_PUBLIC_BACKEND_URL is missing so the pipeline cannot run npm run build
(next build) with an invalid config; implement this by inserting a step before
the "===== Build Application =====" / npm run build step that checks for
NEXT_PUBLIC_BACKEND_URL (exit non‑zero and echo a clear error if unset or empty)
so the workflow fails fast when the variable is absent.

Comment on lines +18 to +25
uses: appleboy/ssh-action@v1.0.3
env:
SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }}
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

appleboy/ssh-action fingerprint parameter support documentation

💡 Result:

appleboy/ssh-action does support a fingerprint input.

  • Where it’s documented (official):
    • In action.yml, the input is defined as:
      • fingerprint: “SHA256 fingerprint of the host public key for verification to prevent MITM attacks.” (and it’s passed through as INPUT_FINGERPRINT). [1]
      • There is also proxy_fingerprint for jump/proxy host verification. [1]
    • In the README under “Host Fingerprint Verification”, it explains why to verify, shows how to obtain a host key fingerprint, and shows usage:
      • with: fingerprint: ${{ secrets.FINGERPRINT }}. [2]

Sources

  • [1] appleboy/ssh-actionaction.yml (inputs, including fingerprint / proxy_fingerprint) (github.com)
  • [2] appleboy/ssh-action — README “Host Fingerprint Verification” section (github.com)

Citations:


🏁 Script executed:

#!/bin/bash
# Search for any existing usage of fingerprint in workflows within the repo
rg "fingerprint" .github/workflows/ --type yaml

Repository: ProjectTech4DevAI/kaapi-frontend

Length of output: 58


🌐 Web query:

appleboy/ssh-action@v1.0.3 github action supported parameters inputs

💡 Result:

appleboy/ssh-action@v1.0.3 supports these with: inputs (GitHub Actions parameters): [1]

  • host
  • port (default: 22)
  • passphrase
  • username
  • password
  • sync
  • use_insecure_cipher
  • cipher
  • timeout (default: 30s)
  • command_timeout (default: 10m)
  • key
  • key_path
  • fingerprint
  • proxy_host
  • proxy_port (default: 22)
  • proxy_username
  • proxy_password
  • proxy_passphrase
  • proxy_timeout (default: 30s)
  • proxy_key
  • proxy_key_path
  • proxy_fingerprint
  • proxy_cipher
  • proxy_use_insecure_cipher
  • script
  • script_stop
  • envs
  • envs_format
  • debug
  • allenvs
  • request_pty

Source: action.yml for tag v1.0.3. [1]

References:
[1] (github.com)

Citations:


Add SSH host key fingerprint verification.

The SSH action is configured with key auth, but no host fingerprint pinning. That weakens MITM protection during deployment. The appleboy/ssh-action@v1.0.3 action supports the fingerprint parameter for this purpose.

Suggested hardening
         with:
           host: ${{ secrets.EC2_HOST }}
           username: ${{ secrets.EC2_USER }}
           key: ${{ secrets.EC2_SSH_KEY }}
+          fingerprint: ${{ secrets.EC2_HOST_FINGERPRINT }}
           script_stop: true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uses: appleboy/ssh-action@v1.0.3
env:
SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }}
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
uses: appleboy/ssh-action@v1.0.3
env:
SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }}
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
fingerprint: ${{ secrets.EC2_HOST_FINGERPRINT }}
script_stop: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-staging.yml around lines 18 - 25, Add SSH host key
fingerprint verification to the appleboy/ssh-action@v1.0.3 invocation by
supplying the fingerprint parameter (use a repository secret like
SSH_HOST_FINGERPRINT) alongside the existing with: host/username/key entries;
update the workflow to read the fingerprint from secrets and pass it into the
action so the action performs host key pinning and prevents MITM attacks during
deployments.

Comment on lines +35 to +45
echo "===== Stop Running Application ====="
pm2 stop "$SCRIPT_NAME" || true

echo "===== Install Dependencies ====="
npm ci

echo "===== Build Application ====="
npm run build

echo "===== Start Application ====="
pm2 start "$SCRIPT_NAME"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/cd-staging.yml

Repository: ProjectTech4DevAI/kaapi-frontend

Length of output: 1503


Move process stop/reload after a successful build to prevent service downtime on build failures.

The deployment stops the application before running npm ci and npm run build. If either step fails, the set -e on line 27 causes the script to exit before reaching the pm2 start command, leaving the service down.

By moving the stop/reload sequence after the build succeeds, the application continues serving traffic during the build phase. If the build fails, the old version stays running instead of going offline.

Consider using pm2 reload instead of pm2 stop followed by pm2 start for cleaner zero-downtime restarts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-staging.yml around lines 35 - 45, The script currently
stops the PM2 process (pm2 stop "$SCRIPT_NAME") before running npm ci and npm
run build, which can leave the service down if build fails; move the pm2
stop/restart sequence so that npm ci and npm run build run first and only after
they succeed perform the process restart, and replace the stop + start sequence
with pm2 reload "$SCRIPT_NAME" (or pm2 reload ecosystem file) to achieve a
zero-downtime restart; ensure the commands referencing SCRIPT_NAME and the pm2
invocation are relocated after the build steps and that failures in npm ci/npm
run build do not stop a currently running instance.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
.github/workflows/cd-production.yml (2)

32-33: ⚠️ Potential issue | 🟠 Major

Replace git pull with deterministic branch sync.

Line 33 can deploy a merged/dirty state. Use fetch + hard reset to origin/release instead.

Suggested fix
             echo "=== Fetch Latest Code ==="
-            git pull origin release
+            git fetch --prune origin release
+            git reset --hard origin/release
+            git clean -fdx
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 32 - 33, Replace the
non-deterministic git pull in the deployment step with an explicit fetch and
hard reset to the remote branch: instead of running "git pull origin release"
update the workflow to run "git fetch origin release" followed by "git reset
--hard origin/release" (optionally add a shallow fetch depth) so the working
tree is deterministically synced to origin/release before building or deploying.

41-42: ⚠️ Potential issue | 🟠 Major

Fail fast when required build-time env vars are missing.

next build can succeed with missing runtime-critical config. Add an explicit guard before Line 42.

Suggested fix
             echo "=== Build Application ==="
+            : "${NEXT_PUBLIC_BACKEND_URL:?NEXT_PUBLIC_BACKEND_URL is required for production build}"
             npm run build
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 41 - 42, Before running the
build step (the npm run build / next build invocation), add a shell guard that
checks the required build-time environment variables and exits non-zero if any
are missing; implement this by enumerating the required names (e.g.,
NEXT_PUBLIC_API_URL, NEXTAUTH_URL, etc.) in a list, iterating over them in a
small bash snippet that tests each with [ -z "${VAR}" ] and prints which are
missing, then exit 1 if any were empty—place this check immediately before the
npm run build line so the workflow fails fast on missing build-time env vars.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/cd-production.yml:
- Around line 22-25: Add host key pinning for the appleboy/ssh-action@v1.0.3 SSH
step by providing the `fingerprint` input so the EC2 host identity is verified;
update the SSH action block that currently contains `host`, `username`, `key`,
and `script_stop` to include `fingerprint: "<expected_host_key_fingerprint>"`
(replace with the actual EC2 SSH host key fingerprint) to enforce host key
verification and prevent MITM.
- Around line 35-45: Replace the unreliable pm2 start call with a
restart-or-start flow: attempt pm2 restart "$SCRIPT_NAME" first and if that
fails fall back to starting npm as a named process (e.g., pm2 start npm --name
"$SCRIPT_NAME" -- start) so PM2 treats the process as the previously registered
app; update the block that currently calls pm2 stop "$SCRIPT_NAME" and pm2 start
"$SCRIPT_NAME" to use pm2 restart "$SCRIPT_NAME" || pm2 start npm --name
"$SCRIPT_NAME" -- start (keeping npm ci and npm run build intact).

---

Duplicate comments:
In @.github/workflows/cd-production.yml:
- Around line 32-33: Replace the non-deterministic git pull in the deployment
step with an explicit fetch and hard reset to the remote branch: instead of
running "git pull origin release" update the workflow to run "git fetch origin
release" followed by "git reset --hard origin/release" (optionally add a shallow
fetch depth) so the working tree is deterministically synced to origin/release
before building or deploying.
- Around line 41-42: Before running the build step (the npm run build / next
build invocation), add a shell guard that checks the required build-time
environment variables and exits non-zero if any are missing; implement this by
enumerating the required names (e.g., NEXT_PUBLIC_API_URL, NEXTAUTH_URL, etc.)
in a list, iterating over them in a small bash snippet that tests each with [ -z
"${VAR}" ] and prints which are missing, then exit 1 if any were empty—place
this check immediately before the npm run build line so the workflow fails fast
on missing build-time env vars.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b6b14c7-3d4b-475f-94d7-3ff376c20f36

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3d49c and 725f60f.

📒 Files selected for processing (2)
  • .github/workflows/cd-production.yml
  • .github/workflows/cd-staging.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/cd-staging.yml

Comment on lines +35 to +45
echo "=== Stop Running Application ==="
pm2 stop "$SCRIPT_NAME" || true

echo "=== Install Dependencies ==="
npm ci

echo "=== Build Application ==="
npm run build

echo "=== Start Application ==="
pm2 start "$SCRIPT_NAME"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Check for PM2 ecosystem files (if none, app-name-only start is suspicious):"
fd -HI 'ecosystem*.js'
fd -HI 'ecosystem*.cjs'
fd -HI 'ecosystem*.json'
fd -HI 'ecosystem*.yml'
fd -HI 'ecosystem*.yaml'

echo "Inspect package scripts:"
rg -n '"scripts"\s*:\s*\{' -A12 package.json

echo "Inspect PM2 usage in workflows:"
rg -n 'PM2_APP_NAME|pm2 (start|restart|stop|describe)' -C2 .github/workflows

Repository: ProjectTech4DevAI/kaapi-frontend

Length of output: 2308


🏁 Script executed:

#!/bin/bash

# Check if there are any other deployment scripts or PM2 config references
echo "=== Search for PM2 config patterns ==="
rg -i 'pm2.*config|ecosystem' .github/workflows

echo "=== Check full context of pm2 start usage ==="
rg -B5 -A5 'pm2 start.*SCRIPT_NAME' .github/workflows

echo "=== Check if there are any error logs or related issues in repo ==="
find . -name "*.md" -type f | head -20 | xargs grep -l 'pm2\|deployment' 2>/dev/null || true

Repository: ProjectTech4DevAI/kaapi-frontend

Length of output: 967


🌐 Web query:

PM2 start command behavior: when given an app name vs script path file extension

💡 Result:

What pm2 start does depends on what the argument resolves to

PM2 documents start as accepting either a file path or an existing app name / PM2 id: start [options] <file|json|stdin|app_name|pm_id…>.[2]

1) If you pass a script/path (e.g., app.js, dist/server.js)

  • PM2 registers a new process in its process list and starts it in the background.[1]
  • The default PM2 process name becomes the script filename without its extension (e.g., app.js → name app) unless you override with --name/-n.[1][2]

2) If you pass an existing PM2 app name (e.g., pm2 start app)

  • In the normal “routine” workflow, once a process is already in the process list, you manage it by name; pm2 start app is used to start that process again (after a stop) using its registered entry.[1]

3) If you pass something without an extension and it’s treated as a file

  • PM2 maps interpreters by extension (e.g., .js→node, .py→python, etc.). If there is no extension, PM2 documents that the app is started as a binary file.[1]

Ecosystem file case (config vs “just a .js script”)

  • An ecosystem file is typically ecosystem.config.js; pm2 start (with no args) will run all apps from that file, and pm2 start /path/to/ecosystem.config.js loads it explicitly.[3]
  • You can target a single app from the ecosystem with pm2 start --only <app_name>.[3] (This relies on app names defined inside the ecosystem file, not script extensions.)

Sources: PM2 Process Management guide[1], PM2 CLI reference[2], PM2 Ecosystem File guide[3].


Use restart-or-start PM2 flow; current start target is unreliable.

pm2 start "$SCRIPT_NAME" with a plain app name (no file extension) is unreliable. PM2 may fail to start the stopped app because it will attempt to treat the name as a file path first. After stopping, the app remains registered; use pm2 restart if it exists, otherwise start npm explicitly as a named process.

Suggested fix
-            echo "=== Stop Running Application ==="
-            pm2 stop "$SCRIPT_NAME" || true
@@
-            echo "=== Start Application ==="
-            pm2 start "$SCRIPT_NAME"
+            echo "=== Start/Restart Application ==="
+            if pm2 describe "$SCRIPT_NAME" >/dev/null 2>&1; then
+              pm2 restart "$SCRIPT_NAME" --update-env
+            else
+              pm2 start npm --name "$SCRIPT_NAME" -- start
+            fi
+            pm2 save
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "=== Stop Running Application ==="
pm2 stop "$SCRIPT_NAME" || true
echo "=== Install Dependencies ==="
npm ci
echo "=== Build Application ==="
npm run build
echo "=== Start Application ==="
pm2 start "$SCRIPT_NAME"
echo "=== Install Dependencies ==="
npm ci
echo "=== Build Application ==="
npm run build
echo "=== Start/Restart Application ==="
if pm2 describe "$SCRIPT_NAME" >/dev/null 2>&1; then
pm2 restart "$SCRIPT_NAME" --update-env
else
pm2 start npm --name "$SCRIPT_NAME" -- start
fi
pm2 save
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 35 - 45, Replace the
unreliable pm2 start call with a restart-or-start flow: attempt pm2 restart
"$SCRIPT_NAME" first and if that fails fall back to starting npm as a named
process (e.g., pm2 start npm --name "$SCRIPT_NAME" -- start) so PM2 treats the
process as the previously registered app; update the block that currently calls
pm2 stop "$SCRIPT_NAME" and pm2 start "$SCRIPT_NAME" to use pm2 restart
"$SCRIPT_NAME" || pm2 start npm --name "$SCRIPT_NAME" -- start (keeping npm ci
and npm run build intact).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/cd-staging.yml:
- Around line 20-22: The CI sets SCRIPT_NAME but does not forward it into the
remote ssh steps; update the appleboy/ssh-action steps to pass SCRIPT_NAME via
the with.envs map so the remote shell sees the app name (use the existing
secrets.PM2_APP_NAME value). Specifically, add SCRIPT_NAME: ${{
secrets.PM2_APP_NAME }} to the with.envs of the appleboy/ssh-action invocations
(both the deploy step around the first ssh-action and the later one referenced
at lines 37–46) so commands run remotely with a populated app name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 846964fd-bb85-4d73-95d7-089eed4fb331

📥 Commits

Reviewing files that changed from the base of the PR and between 725f60f and ff4167b.

📒 Files selected for processing (2)
  • .github/workflows/cd-production.yml
  • .github/workflows/cd-staging.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/cd-production.yml

Comment on lines +20 to +22
env:
SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }}
with:
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

appleboy/ssh-action v1.0.3 envs input required to pass step env variables to remote script

💡 Result:

Yes. In appleboy/ssh-action@v1.0.3, step/job env: variables exist only inside the GitHub Actions runner/container; they are not automatically available in the remote SSH session. To make them available to your remote script, you must (1) define them in env: and (2) whitelist their names via with: envs:. [1]

- name: Deploy
  uses: appleboy/ssh-action@v1.0.3
  env:
    APP_ENV: production
    API_URL: ${{ vars.API_URL }}
    SECRET:  ${{ secrets.SECRET }}
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USERNAME }}
    key: ${{ secrets.SSH_KEY }}
    envs: APP_ENV,API_URL,SECRET
    script: |
      echo "APP_ENV=$APP_ENV"
      ./deploy.sh

Notes:

  • envs is a comma-separated allowlist of variable names to forward. [1]
  • If you omit envs, your remote script won’t see those variables (common “why is $SECRET empty?” symptom). [2]
  • allenvs only forwards variables with GITHUB_ and INPUT_ prefixes, not your custom names. [1]

Sources: [1] appleboy/ssh-action README (inputs + “Pass environment variables” example), [2] appleboy/ssh-action issue discussion about env vars not being available remotely.


Pass SCRIPT_NAME into the remote shell explicitly.

Line 21 sets SCRIPT_NAME, but it is not forwarded to the remote session. In appleboy/ssh-action, custom env vars must be listed in with.envs; otherwise Lines 37 and 46 will execute with an empty app name.

Proposed fix
       - name: Deploy via SSH
         uses: appleboy/ssh-action@v1.0.3
         env:
           SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }}
         with:
           host: ${{ secrets.EC2_HOST }}
           username: ${{ secrets.EC2_USER }}
           key: ${{ secrets.EC2_SSH_KEY }}
+          envs: SCRIPT_NAME
           script_stop: true
           script: |

Also applies to: 37-46

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-staging.yml around lines 20 - 22, The CI sets
SCRIPT_NAME but does not forward it into the remote ssh steps; update the
appleboy/ssh-action steps to pass SCRIPT_NAME via the with.envs map so the
remote shell sees the app name (use the existing secrets.PM2_APP_NAME value).
Specifically, add SCRIPT_NAME: ${{ secrets.PM2_APP_NAME }} to the with.envs of
the appleboy/ssh-action invocations (both the deploy step around the first
ssh-action and the later one referenced at lines 37–46) so commands run remotely
with a populated app name.

on:
push:
branches:
- release
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Production uses the release branch, as discussed in the GitHub issue.

For reference, you can check it here: #22 (comment)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (4)
.github/workflows/cd-production.yml (4)

37-47: ⚠️ Potential issue | 🟠 Major

Replace stop/start with restart-or-start PM2 flow.

Line 47 still depends on pm2 start "$PM2_APP_NAME" path; first deploys or registration drift can fail startup.

Suggested fix
-            echo "=== Stop Running Application ==="
-            pm2 stop "$PM2_APP_NAME" || true
@@
-            echo "=== Start Application ==="
-            pm2 start "$PM2_APP_NAME"
+            echo "=== Start/Restart Application ==="
+            if pm2 describe "$PM2_APP_NAME" >/dev/null 2>&1; then
+              pm2 restart "$PM2_APP_NAME" --update-env
+            else
+              pm2 start npm --name "$PM2_APP_NAME" -- start
+            fi
+            pm2 save
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 37 - 47, The workflow
currently uses "pm2 stop \"$PM2_APP_NAME\"" and then "pm2 start
\"$PM2_APP_NAME\"" which can fail when the app isn't registered; replace that
stop/start sequence with a restart-or-start flow so deployments work whether the
process exists or not: use pm2 restart "$PM2_APP_NAME" (or pm2 restart
"$PM2_APP_NAME" --update-env) and fall back to pm2 start "$PM2_APP_NAME" if
restart fails, keeping the same PM2_APP_NAME variable and ensuring the commands
run after build.

34-35: ⚠️ Potential issue | 🟠 Major

Use deterministic branch sync instead of git pull.

Line 35 can merge or keep drifted state on the server; deployment should force exact origin/release.

Suggested fix
             echo "=== Fetch Latest Code ==="
-            git pull origin release
+            git fetch --prune origin
+            git checkout -B release origin/release
+            git reset --hard origin/release
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 34 - 35, Replace the
non-deterministic "git pull origin release" with an explicit fetch and
hard-reset to the remote branch so the deployment always matches origin/release;
update the workflow to run a deterministic sequence such as fetching from origin
(e.g., "git fetch --prune origin") and then resetting or recreating the local
branch to exactly match origin/release (e.g., "git reset --hard origin/release"
or "git checkout -B release origin/release") instead of using "git pull origin
release".

24-27: ⚠️ Potential issue | 🟠 Major

Pin the EC2 SSH host key fingerprint.

Line 24-Line 27 still omit host key pinning, so SSH target identity is not enforced during deploy.

Suggested fix
         with:
           host: ${{ secrets.EC2_HOST }}
           username: ${{ secrets.EC2_USER }}
           key: ${{ secrets.EC2_SSH_KEY }}
+          fingerprint: ${{ secrets.EC2_HOST_FINGERPRINT }}
           script_stop: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 24 - 27, The workflow
currently sets host/username/key but doesn’t pin the EC2 SSH host key; update
the step that uses host/username/key (the SSH/deploy action) to enforce host key
verification by adding a pinned host key/known_hosts entry (e.g., a host_key or
known_hosts parameter referencing a secret containing the EC2 server's public
key or fingerprint) so the action verifies the target identity instead of
accepting any host; ensure the secret value is created from the EC2 instance's
SSH host public key or its fingerprint and referenced in the step alongside
host, username, and key.

20-23: ⚠️ Potential issue | 🟠 Major

Fail fast when required build-time env var is missing.

npm run build can succeed with an invalid runtime config if required public env vars are absent.

Suggested fix
         env:
           PM2_APP_NAME: ${{ secrets.PM2_APP_NAME }}
           BUILD_DIRECTORY: ${{ secrets.BUILD_DIRECTORY }}
+          NEXT_PUBLIC_BACKEND_URL: ${{ secrets.NEXT_PUBLIC_BACKEND_URL }}
@@
             echo "=== Build Application ==="
+            : "${NEXT_PUBLIC_BACKEND_URL:?NEXT_PUBLIC_BACKEND_URL is required for production build}"
             npm run build

Also applies to: 43-44

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cd-production.yml around lines 20 - 23, Add a pre-build
check step in the GitHub Actions job that verifies required build-time env vars
(PM2_APP_NAME and BUILD_DIRECTORY) are set and exits non-zero if any are missing
so the workflow fails fast before running npm run build; place this check before
the build step and mirror it for the other job that also uses those vars (the
block referenced by the second occurrence), referencing the env keys
PM2_APP_NAME and BUILD_DIRECTORY in the validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/cd-production.yml:
- Around line 37-47: The workflow currently uses "pm2 stop \"$PM2_APP_NAME\""
and then "pm2 start \"$PM2_APP_NAME\"" which can fail when the app isn't
registered; replace that stop/start sequence with a restart-or-start flow so
deployments work whether the process exists or not: use pm2 restart
"$PM2_APP_NAME" (or pm2 restart "$PM2_APP_NAME" --update-env) and fall back to
pm2 start "$PM2_APP_NAME" if restart fails, keeping the same PM2_APP_NAME
variable and ensuring the commands run after build.
- Around line 34-35: Replace the non-deterministic "git pull origin release"
with an explicit fetch and hard-reset to the remote branch so the deployment
always matches origin/release; update the workflow to run a deterministic
sequence such as fetching from origin (e.g., "git fetch --prune origin") and
then resetting or recreating the local branch to exactly match origin/release
(e.g., "git reset --hard origin/release" or "git checkout -B release
origin/release") instead of using "git pull origin release".
- Around line 24-27: The workflow currently sets host/username/key but doesn’t
pin the EC2 SSH host key; update the step that uses host/username/key (the
SSH/deploy action) to enforce host key verification by adding a pinned host
key/known_hosts entry (e.g., a host_key or known_hosts parameter referencing a
secret containing the EC2 server's public key or fingerprint) so the action
verifies the target identity instead of accepting any host; ensure the secret
value is created from the EC2 instance's SSH host public key or its fingerprint
and referenced in the step alongside host, username, and key.
- Around line 20-23: Add a pre-build check step in the GitHub Actions job that
verifies required build-time env vars (PM2_APP_NAME and BUILD_DIRECTORY) are set
and exits non-zero if any are missing so the workflow fails fast before running
npm run build; place this check before the build step and mirror it for the
other job that also uses those vars (the block referenced by the second
occurrence), referencing the env keys PM2_APP_NAME and BUILD_DIRECTORY in the
validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 28e9a87d-11c4-41cd-ad33-00f71346b91b

📥 Commits

Reviewing files that changed from the base of the PR and between ff4167b and 8d79917.

📒 Files selected for processing (2)
  • .github/workflows/cd-production.yml
  • .github/workflows/cd-staging.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/cd-staging.yml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants