Due: Next Wednesday
Goal
By the end of this assignment, your project should support Continuous Deployment, or CD.
That means when you push working code to GitHub, your project should automatically update on the server.
Your system should:
Run CI tests automatically
Deploy only if tests pass
Update your project on 10.192.145.179
Rebuild the frontend
Restart the backend using PM2
Make the new version live on your assigned 41xx port
Important Server Note
All projects are hosted on:
10.192.145.179
This server is behind a firewall. Because of that, a normal GitHub-hosted Actions runner cannot SSH into it.
Instead, you will use a GitHub self-hosted runner installed on 10.192.145.179.
PM2 is already installed on the server.
Part 1: Confirm Your App Runs Manually
SSH into the server:
ssh yourusername@10.192.145.179
Go to your project directory:
cd ~/sd/YOUR-PROJECT-NAME
Install root dependencies:
npm install
Build the client:
cd client
npm install
npm run build
Install server dependencies:
cd ../server
npm install
Start the server manually:
npm start
Open your app in a browser:
http://10.192.145.179:41xx
Replace 41xx with your assigned port.
Do not continue until your app runs manually.
Part 2: Put Your App Under PM2
Stop the manually running server with Ctrl+C.
Go to the server directory:
cd ~/sd/YOUR-PROJECT-NAME/server
Start the app with PM2:
pm2 start index.js --name YOUR-PROJECT-NAME
Check that it is running:
pm2 list
Save the PM2 process list:
pm2 save
Now open your app again:
http://10.192.145.179:41xx
Your app should still be running.
Part 3: Create a Deployment Script
In the root of your project, create a file named:
deploy.sh
Put this in the file:
#!/bin/bash
set -eecho "Starting deployment..."git pullecho "Installing root dependencies..."
npm installecho "Building client..."
cd client
npm install
npm run build
echo "Installing server dependencies..."
cd ../server
npm install
echo "Restarting app with PM2..."
pm2 restart YOUR-PROJECT-NAME
echo "Deployment complete."
Replace YOUR-PROJECT-NAME with the exact PM2 name you used earlier.
Make the script executable:
chmod +x deploy.sh
Test it manually:
./deploy.sh
Refresh your app in the browser and make sure it still works.
Part 4: Install a GitHub Self-Hosted Runner
In GitHub, open your repository.
Go to:
Settings → Actions → Runners → New self-hosted runner
Choose:
Linux
Choose architecture:
x64
GitHub will show you commands to run on the server.
On 10.192.145.179, create a runner directory:
mkdir -p ~/actions-runner
cd ~/actions-runner
Then run the commands GitHub gives you.
When GitHub asks for labels, you may accept the defaults or add:
cd
When setup is complete, start the runner:
./run.sh
Leave this running while testing.
For this assignment, it is acceptable to run the self-hosted runner manually.
Part 5: Create the CD Workflow
In your project, create this file:
.github/workflows/cd.yml
If the folders do not exist, create them.
Put this in cd.yml:
name: CD
on:
workflow_run:
workflows: ["CI"]
types:
- completed
jobs:
deploy:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'main' }}
runs-on: self-hosted
steps:
- name: Deploy application
run: |
cd ~/sd/YOUR-PROJECT-NAME
./deploy.sh
Replace YOUR-PROJECT-NAME with your actual project directory name.
This workflow means:
CI runs first.
CD runs only if CI succeeds.
CD runs only for pushes to main.
Deployment runs on the self-hosted runner on 10.192.145.179.
The deploy.sh script updates, rebuilds, and restarts the app.
Part 6: Commit and Push
Add your files:
git add .
Commit your changes:
git commit -m "Add CD deployment workflow"
Push to GitHub:
git push origin main
Now go to GitHub → Actions.
You should see CI run first. If CI succeeds, CD should run next.
Part 7: Prove That CD Works
Make a small visible change to your frontend.
For example, change a heading, title, or paragraph on the home page.
Commit and push the change:
git add .
git commit -m "Test CD with visible frontend change"
git push origin main
Watch GitHub Actions.
After CI and CD finish, open:
http://10.192.145.179:41xx
You should see your change live.
That is your proof that CD is working.
What to Submit
Submit a short report with:
Your GitHub repository URL
Your live app URL
A screenshot of your successful CI run
A screenshot of your successful CD run
A screenshot of your PM2 process list
A brief explanation of what happens when you push to main
A brief description of one problem you ran into and how you fixed it
Grading Checklist
Your assignment will be graded on whether:
The app runs correctly on 10.192.145.179
The app is managed by PM2
deploy.sh exists and works manually
The GitHub self-hosted runner is connected
.github/workflows/cd.yml exists
CD runs only after CI succeeds
A visible frontend change is automatically deployed
The submission includes the required screenshots and explanation
Common Problems
CD does not start.
Check:
Is your CI workflow named exactly CI?
Are you pushing to main?
Is the self-hosted runner online?
Does GitHub show the runner under Settings → Actions → Runners?
The workflow says no runner is available.
Go back to the runner directory:
cd ~/actions-runner
Start the runner again:
./run.sh
The deployment cannot find the project directory.
Check this line in cd.yml:
cd ~/sd/YOUR-PROJECT-NAME
Make sure the directory exists on the server.
PM2 restart fails.
Check the PM2 process list:
pm2 list
Make sure the process name in deploy.sh exactly matches the PM2 process name.
The app deploys but the page does not change.
Check:
Did npm run build complete successfully?
Is Express serving client/dist?
Are you looking at the correct 41xx port?
Try a hard refresh in the browser.
Reflection Questions
Answer these in your report:
What is the difference between CI and CD?
Why should CD only run after CI passes?
Why do we need a self-hosted runner for this server?
What role does PM2 play?
What is still fragile or simple about this deployment setup?
