Skip to content

Commit 845eb01

Browse files
authored
Revise README for deployment modes and CI updates
Updated README to reflect new deployment modes and CI/CD improvements.
1 parent 15d2fd7 commit 845eb01

1 file changed

Lines changed: 77 additions & 22 deletions

File tree

README.md

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
# 📋 PERN Task Manager — GitHub Actions CI/CD Pipeline
1+
# PERN Task Manager — GitHub Actions CI/CD Pipeline
22

33
![CI/CD](https://img.shields.io/badge/CI%2FCD-GitHub_Actions-2088FF?style=for-the-badge&logo=githubactions&logoColor=white)
4+
![Kubernetes](https://img.shields.io/badge/Kubernetes-326CE5?style=for-the-badge&logo=kubernetes&logoColor=white)
45
![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white)
56
![AWS](https://img.shields.io/badge/AWS_EC2-FF9900?style=for-the-badge&logo=amazonaws&logoColor=white)
67
![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white)
78
![React](https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)
89
![Node.js](https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
910
![Nginx](https://img.shields.io/badge/Nginx-009639?style=for-the-badge&logo=nginx&logoColor=white)
1011

11-
A full-stack PERN (PostgreSQL, Express, React, Node.js) task manager app deployed to AWS EC2 via a fully automated CI/CD pipeline using GitHub Actions and Docker.
12+
A full-stack PERN (PostgreSQL, Express, React, Node.js) task manager app with two deployment modes — Docker Compose on AWS EC2 and Kubernetes via kind/k3s — both automated through GitHub Actions.
1213

13-
> **v2 of this project** — previously deployed with Jenkins. Migrated to GitHub Actions to remove the need for a separate CI server. See [task-manager-cicd-pipeline](https://github.com/kithupag/task-manager-cicd-pipeline) for the Jenkins version.
14+
> **v2 of this project** — previously deployed with Jenkins. Migrated to GitHub Actions and extended with Kubernetes support. See [task-manager-cicd-pipeline](https://github.com/yourusername/task-manager-cicd-pipeline) for the Jenkins version.
1415
1516
---
1617

17-
## 🏗️ Architecture
18+
## Architecture
1819

1920
```
2021
Developer → GitHub Push → GitHub Actions → Docker Hub → AWS EC2
@@ -39,8 +40,9 @@ Developer → GitHub Push → GitHub Actions → Docker Hub → AWS EC2
3940

4041
---
4142

42-
## 🚀 Pipeline Stages
43+
## Pipeline Stages
4344

45+
### Mode 1 — Docker Compose (EC2)
4446
```
4547
build-and-push ──────────────────────────► deploy
4648
├── Checkout code ├── Checkout code
@@ -49,11 +51,24 @@ build-and-push ─────────────────────
4951
└── Build & push server image └── SSH → docker compose up -d
5052
```
5153

54+
### Mode 2 — Kubernetes (kind)
55+
```
56+
build-and-push ──────────────────────────► deploy
57+
├── Checkout code ├── Checkout code
58+
├── Log in to Docker Hub ├── Create kind cluster
59+
├── Build & push client image ├── Update image tags
60+
└── Build & push server image ├── kubectl apply all manifests
61+
├── Wait for postgres ready
62+
├── Create database table
63+
├── Wait for backend + frontend
64+
└── Run API smoke tests
65+
```
66+
5267
The `deploy` job has `needs: build-and-push` — it only runs if the build succeeds. Both jobs run on fresh GitHub-hosted Ubuntu VMs.
5368

5469
---
5570

56-
## 📁 Project Structure
71+
## Project Structure
5772

5873
```
5974
task-manager-github-actions/
@@ -80,14 +95,23 @@ task-manager-github-actions/
8095
│ ├── Dockerfile
8196
│ └── package.json
8297
98+
├── k8s/ # Kubernetes manifests
99+
│ ├── postgres/
100+
│ │ ├── deployment.yaml # Postgres Deployment + Service + PVC
101+
│ │ └── secret.yaml # DB credentials as k8s Secret
102+
│ ├── backend/
103+
│ │ └── deployment.yaml # Backend Deployment + Service
104+
│ └── frontend/
105+
│ └── deployment.yaml # Frontend Deployment + NodePort Service
106+
83107
├── database.sql # Mounted into postgres on fresh deploy
84-
├── docker-compose.yaml # Production compose — image tags pinned by pipeline
108+
├── docker-compose.yaml # Local dev + EC2 compose deployment
85109
└── README.md
86110
```
87111

88112
---
89113

90-
## 🔧 Key Technical Decisions
114+
## Key Technical Decisions
91115

92116
**GitHub Actions over Jenkins**
93117
Jenkins requires a dedicated server running 24/7. GitHub Actions runs on GitHub's infrastructure — no server to maintain, no Docker socket to mount, no SSH keys to manage inside a container. The pipeline logic is identical, the operational overhead is zero.
@@ -119,7 +143,7 @@ All three containers report real status. Backend and frontend are checked via HT
119143

120144
---
121145

122-
## 🔄 Comparison with Jenkins Version
146+
## Comparison with Jenkins Version
123147

124148
| | Jenkins Version | GitHub Actions Version |
125149
|--|----------------|----------------------|
@@ -134,7 +158,7 @@ All three containers report real status. Backend and frontend are checked via HT
134158

135159
---
136160

137-
## 🛠️ Local Development Setup
161+
## Local Development Setup
138162

139163
### Prerequisites
140164
- Docker & Docker Compose
@@ -168,7 +192,7 @@ DB_NAME=todo_db
168192

169193
---
170194

171-
## 📡 API Endpoints
195+
## API Endpoints
172196

173197
| Method | Endpoint | Description |
174198
|--------|----------|-------------|
@@ -180,7 +204,7 @@ DB_NAME=todo_db
180204

181205
---
182206

183-
## ⚙️ Replicating This Pipeline
207+
## Replicating This Pipeline
184208

185209
### GitHub Secrets Required
186210

@@ -221,7 +245,23 @@ mkdir -p ~/task-manager
221245

222246
---
223247

224-
## 💡 Lessons Learned
248+
## Kubernetes Concepts Used
249+
250+
**Deployment** — manages desired pod state. If a pod crashes Kubernetes automatically replaces it.
251+
252+
**Service** — provides stable DNS names (, , ) so pods can reach each other regardless of their changing IPs.
253+
254+
**PersistentVolumeClaim** — requests persistent storage for postgres so data survives pod restarts.
255+
256+
**Secret** — stores database credentials as base64-encoded values injected as environment variables — never hardcoded in manifests.
257+
258+
**NodePort Service** — exposes the frontend on port 30080 on every node, accessible from outside the cluster.
259+
260+
**Readiness + Liveness Probes** — readiness controls when traffic is sent to a pod, liveness restarts pods that stop responding. Both use HTTP checks.
261+
262+
---
263+
264+
## Lessons Learned
225265

226266
**From migrating Jenkins → GitHub Actions:**
227267
- Pipeline concepts are identical across tools — triggers, jobs, steps, secrets. Learning one makes the next trivial.
@@ -230,29 +270,44 @@ mkdir -p ~/task-manager
230270
- `needs:` in GitHub Actions is more explicit than Jenkins stage ordering — you declare job dependencies intentionally.
231271
- A running container might be from an old image — always verify the tag matches your latest build number before debugging.
232272

273+
**From migrating to Kubernetes:**
274+
- `kubectl apply` succeeds even if the pod crashes seconds later — always verify with `kubectl wait`
275+
- Pod ready does not mean application ready — use `pg_isready` not just Kubernetes readiness probes
276+
- `-it` flags don't work in CI pipelines — no TTY available, always remove from `kubectl exec` in automation
277+
- Kubernetes service names are DNS — containers reach each other by service name, not IP
278+
- `kubectl describe pod` is more useful than `kubectl logs` when a pod won't start
279+
233280
**Carried over from Jenkins version:**
234281
- Always use relative URLs in React — `localhost` in fetch calls breaks in production
235282
- `docker compose ps` showing `Up` is not the same as healthy — always add health checks
236283
- Env vars with duplicate keys in JS objects silently use the last value — never hardcode credentials
237284

238285
---
239286

240-
## 📌 Improvements
287+
## 📌
241288

242-
### Completed
243-
- [x] Migrated from Jenkins to GitHub Actions
289+
### Completed
290+
- [x] Migrated from Jenkins to GitHub Actions — zero CI server overhead
244291
- [x] Automated database table creation via `docker-entrypoint-initdb.d/`
245292
- [x] Docker health checks on all services
246293
- [x] Pinned image tags — exact build number deployed, never `:latest`
247-
248-
### 🔜 Up Next
249-
- [ ] Provision EC2 infrastructure with Terraform
294+
- [x] Kubernetes manifests for all three services
295+
- [x] CI pipeline deploys to real kind cluster on every push
296+
- [x] Readiness and liveness probes on all pods
297+
- [x] Secrets management via Kubernetes Secrets
298+
- [x] Persistent storage for database via PVC
299+
- [x] Automated API smoke tests after deployment
300+
301+
### Up Next
302+
- [ ] Helm charts — package manifests with configurable values
303+
- [ ] Multiple environments — dev, staging, production namespaces
304+
- [ ] Horizontal Pod Autoscaler
305+
- [ ] Provision EKS cluster with Terraform
250306
- [ ] Add security scanning — Trivy, Snyk, Checkov
251-
- [ ] Add Prometheus + Grafana monitoring
252-
- [ ] Migrate to Kubernetes deployment
307+
- [ ] Set up Prometheus + Grafana monitoring
253308

254309
---
255310

256311
## 📄 License
257312

258-
MIT
313+
MIT

0 commit comments

Comments
 (0)