diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe8fb49 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +build +.git +.gitignore +.dockerignore +package-lock.json +yarn.lock diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..2e61b6f --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,66 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + test-backend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + cache-dependency-path: backend/package-lock.json + - name: Install dependencies + run: | + cd backend + npm install + - name: Run tests + run: | + cd backend + npm test + + test-frontend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Install dependencies + run: npm install + - name: Run tests + run: npm test + + build-and-push: + needs: [test-backend, test-frontend] + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - uses: actions/checkout@v3 + - name: Log in to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push Frontend + uses: docker/build-push-action@v4 + with: + context: . + push: true + tags: ghcr.io/${{ github.repository }}/civix-frontend:latest + - name: Build and push Backend + uses: docker/build-push-action@v4 + with: + context: ./backend + push: true + tags: ghcr.io/${{ github.repository }}/civix-backend:latest diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ac6578c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +# Build stage +FROM node:18-alpine as build-stage +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +# Serve stage +FROM nginx:alpine +COPY --from=build-stage /app/build /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..f376f3f --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,8 @@ +node_modules +.git +.gitignore +.dockerignore +package-lock.json +yarn.lock +uploads +cache diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f4e5895 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,20 @@ +# Use official Node.js image +FROM node:18-alpine + +# Set working directory +WORKDIR /app + +# Copy package.json and package-lock.json +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of the application code +COPY . . + +# Expose the port the app runs on +EXPOSE 5000 + +# Start the application +CMD ["npm", "start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d1bf3d5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + mongodb: + image: mongo:latest + ports: + - "27017:27017" + volumes: + - mongo-data:/data/db + + backend: + build: ./backend + ports: + - "5000:5000" + environment: + - MONGO_URI=mongodb://mongodb:27017/civix + - PORT=5000 + depends_on: + - mongodb + + frontend: + build: . + ports: + - "3000:80" + depends_on: + - backend + +volumes: + mongo-data: diff --git a/k8s/base/backend.yaml b/k8s/base/backend.yaml new file mode 100644 index 0000000..6125f2b --- /dev/null +++ b/k8s/base/backend.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend +spec: + replicas: 1 + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + spec: + containers: + - name: backend + image: civix-backend:latest # replace with actual image name + ports: + - containerPort: 5000 + env: + - name: MONGO_URI + value: mongodb://mongodb:27017/civix + - name: PORT + value: "5000" +--- +apiVersion: v1 +kind: Service +metadata: + name: backend +spec: + ports: + - port: 5000 + targetPort: 5000 + selector: + app: backend diff --git a/k8s/base/frontend.yaml b/k8s/base/frontend.yaml new file mode 100644 index 0000000..d4bd4cc --- /dev/null +++ b/k8s/base/frontend.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + replicas: 1 + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: civix-frontend:latest # replace with actual image name + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend +spec: + ports: + - port: 80 + targetPort: 80 + selector: + app: frontend + type: LoadBalancer # Or Ingress for real-world usage diff --git a/k8s/base/mongo.yaml b/k8s/base/mongo.yaml new file mode 100644 index 0000000..f8729a5 --- /dev/null +++ b/k8s/base/mongo.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongodb +spec: + replicas: 1 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + containers: + - name: mongodb + image: mongo:latest + ports: + - containerPort: 27017 + volumeMounts: + - name: mongo-storage + mountPath: /data/db + volumes: + - name: mongo-storage + persistentVolumeClaim: + claimName: mongo-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb +spec: + ports: + - port: 27017 + targetPort: 27017 + selector: + app: mongodb +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mongo-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..db77997 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,25 @@ +provider "aws" { + region = var.aws_region +} + +# Create a VPC +resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" +} + +# Create a Subnet +resource "aws_subnet" "public" { + vpc_id = aws_vpc.main.id + cidr_block = "10.0.1.0/24" + availability_zone = "${var.aws_region}a" +} + +# Create an EKS cluster +# (Requires IAM roles and other configs, keeping it simple for now) +# module "eks" { +# source = "terraform-aws-modules/eks/aws" +# cluster_name = "civix-cluster" +# cluster_version = "1.27" +# subnet_ids = [aws_subnet.public.id] +# vpc_id = aws_vpc.main.id +# } diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..de24eba --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,4 @@ +variable "aws_region" { + description = "AWS region" + default = "us-east-1" +}