diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..d67ee57 --- /dev/null +++ b/.env.local @@ -0,0 +1,15 @@ +# Google OAuth credentials +GOOGLE_ID=843731093025-eol05fgfiajku69sg3b9opvuautbe07v.apps.googleusercontent.com +GOOGLE_SECRET=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 + +# MongoDB connection string - CONTAINS PASSWORD +MONGODB_URI=mongodb+srv://alipeco90_db_user:D7Xr4ExRbiavbE6K@cluster0.bnl24cv.mongodb.net/ + +# NextAuth secret - Use PLAIN TEXT DECODED value here +NEXTAUTH_SECRET=qt9cV37G2WGd1fZtGjNWnh42XSC087HyMGlB349dhfY= + +# Base URL for the application +NEXTAUTH_URL=https://72.61.159.174.nip.io + +# Google API Key - Use PLAIN TEXT DECODED value here +NEXT_PUBLIC_API_KEY=AIzaSyB1e0MSZ4SC_m43jUisDft2p7lPcqem3v8 diff --git a/.env.sample b/.env.sample deleted file mode 100644 index 8ef4ff2..0000000 --- a/.env.sample +++ /dev/null @@ -1,15 +0,0 @@ -# Google OAuth credentials -GOOGLE_ID=your_google_id_here -GOOGLE_SECRET=your_google_secret_here - -# MongoDB connection string -MONGODB_URI=mongodb://localhost:27017 - -# NextAuth secret -NEXTAUTH_SECRET="your_nextauth_secret_here" - -# Base URL for the application -NEXTAUTH_URL=http://localhost:3000 - -# Google API Key -NEXT_PUBLIC_API_KEY=your_google_api_key_here \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b571261..dbd42a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,50 +1,19 @@ -################################## -# Stage 1: Build Stage -################################## -FROM node:18-alpine AS builder +# This is now a single-stage build -# Add metadata for authorship and app identification -LABEL maintainer="Amitabh Soni " \ - app="gemini" \ - stage="build" +FROM node:18-alpine +LABEL maintainer="Amitabh Soni " app="gemini" stage="build" WORKDIR /app -# Install build dependencies +# Copy package files and install dependencies COPY package.json package-lock.json* ./ RUN npm ci -# Copy source and build +# Copy the rest of the application code COPY . . -RUN npm run build - -# Clean up dev dependencies after build -RUN rm -rf node_modules && npm cache clean --force - -################################## -# Stage 2: Production Stage -################################## -FROM node:18-alpine AS production - -# Add metadata for the final image -LABEL maintainer="Amitabh Soni " \ - app="gemini" \ - stage="production" - -WORKDIR /app -# Install only production dependencies -COPY package.json package-lock.json* ./ -RUN npm ci --production && npm cache clean --force - -# Copy minimal required files -COPY --from=builder /app/.next ./.next -COPY --from=builder /app/public ./public -COPY --from=builder /app/next.config.mjs ./ - -# Set production environment -ENV NODE_ENV=production - -EXPOSE 3000 +# Build the application +RUN npm run build -CMD ["npm", "start"] \ No newline at end of file +# Set the command to start the app +CMD ["npm", "start"] diff --git a/Jenkinsfile b/Jenkinsfile index 88172c6..71e7001 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,187 +1,48 @@ -@Library('Shared')_ - pipeline { - agent { label 'dev-server' } + agent { label 'devsecops-agent' } -environment { - SONAR_HOME = tool "Sonar" - DOCKER_IMAGE = "gemininip" - GIT_REPO = "https://github.com/Amitabh-DevOps/dev-gemini-clone.git" - GIT_BRANCH = "kind" - DOCKERHUB_USERNAME = "amitabhdevops" - DOCKER_IMAGE_NAME = "${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}" -} -parameters { - string(name: 'GEMINI_DOCKER_TAG', defaultValue: 'v1', description: 'Setting docker image for latest push') -} -stages { - stage("Clean Workspace") { - steps { - cleanWs() - } - } - stage("Code") { - steps { - // Use GIT_REPO and GIT_BRANCH from environment variables - clone("${GIT_REPO}", "${GIT_BRANCH}") - echo "Code cloning done from ${GIT_REPO} branch ${GIT_BRANCH}." - } - } - stage("Prepare Environment File") { - steps { - prepareEnvFile('.env.local', '.env.local') - } + environment { + SONAR_HOST_URL = "http://sonarqube-sonarqube.sonarqube.svc.cluster.local:9000" + SONAR_PROJECT_KEY = "dev-gemini" } - stage("Build") { - steps { - dockerbuild("${DOCKER_IMAGE}", "${params.GEMINI_DOCKER_TAG}") - echo "Docker image ${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG} built successfully." - } - } - stage("SonarQube Quality Analysis") { - steps { - sonarqube_analysis('Sonar', "${DOCKER_IMAGE}", "${DOCKER_IMAGE}") - } - } - stage("OWASP : Dependency Check") { - steps { - owasp_dependency() - } - } - stage("Sonar Quality Gate Scan") { - steps { - sonarqube_code_quality() + + stages { + stage('Clone Code') { + steps { + echo "--- Cloning source code ---" + git branch: 'feat/kind', url: 'https://github.com/harisamjad0158/dev-gemini-clone.git' + } } - } - stage("Docker Image Security Scan (Trivy)") { - steps { - dockerScanTrivy("${DOCKER_IMAGE}", "${params.GEMINI_DOCKER_TAG}") - echo "Trivy scan completed for ${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG}." + + stage('Test SonarQube Connection') { + steps { + container('sonar') { + withCredentials([string(credentialsId: 'sonarqube-token', variable: 'SONAR_TOKEN')]) { + sh ''' + echo "--- Testing SonarQube Connection ---" + response=$(curl -s -o /dev/null -w "%{http_code}" \ + -u ${SONAR_TOKEN}: \ + ${SONAR_HOST_URL}/api/server/version) + + if [ "$response" = "200" ]; then + echo "✅ SonarQube connection successful!" + else + echo "❌ SonarQube connection failed with HTTP code $response" + exit 1 + fi + ''' + } + } + } } } - stage("Push to DockerHub") { - steps { - dockerpush("dockerHub", "${DOCKER_IMAGE}", "${params.GEMINI_DOCKER_TAG}") - echo "Pushed ${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG} to DockerHub." + + post { + success { + echo "✅ Jenkins and SonarQube are successfully synced!" } - } - // Uncommented and updated the "Run Container" stage to use environment variables - // stage("Run Container") { - // steps { - // dockerRunApp("${DOCKER_IMAGE}", "${params.GEMINI_DOCKER_TAG}", "env_local", "${DOCKER_IMAGE}", "--env-file .env.local -p 3000:3000") - // echo "Container started using ${DOCKER_IMAGE}:${DOCKER_TAG} with container name '${DOCKER_IMAGE}'." - // } - // } - stage("Cleanup Docker Images") { - steps { - script { - sh "docker rmi ${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG} || true" - sh "docker rmi ${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG} || true" - sh "docker image prune -f" - } - echo "Cleaned up Docker image: ${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG}." + failure { + echo "❌ Jenkins could not connect to SonarQube. Check token or URL." } } } -post { - success { - archiveArtifacts artifacts: 'kind/gemini-deployment.yml', followSymlinks: false - build job: "Gemini-CD", parameters: [ - string(name: 'GEMINI_DOCKER_TAG', value: "${params.GEMINI_DOCKER_TAG}"), - string(name: 'DOCKER_IMAGE_NAME', value: "${DOCKER_IMAGE_NAME}"), - ] - echo "Pipeline completed successfully!" - emailext ( - subject: "SUCCESS: Jenkins Pipeline for ${DOCKER_IMAGE}", - body: """ -
-

🎉 Pipeline Execution: SUCCESS 🎉

-

- Hello Team, -

-

- The Jenkins CI pipeline for ${DOCKER_IMAGE} completed successfully! -

- - - - - - - - - - - - - - - - - -
DetailsValues
Git Repository${GIT_REPO}
Branch${GIT_BRANCH}
Docker Image${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG}
-

- Visit Pipeline Logs for more details. -

-

- Thanks,
- Jenkins -

-
- """, - to: "amitabhdevops2024@gmail.com", - from: "jenkins@example.com", - mimeType: 'text/html', - attachmentsPattern: '**/table-report.html' - ) - } - failure { - echo "Pipeline failed. Please check the logs." - emailext ( - subject: "FAILURE: Jenkins Pipeline for ${DOCKER_IMAGE}", - body: """ -
-

🚨 Pipeline Execution: FAILURE 🚨

-

- Hello Team, -

-

- Unfortunately, the Jenkins CI pipeline for ${DOCKER_IMAGE} has failed. -

- - - - - - - - - - - - - - - - - -
DetailsValues
Git Repository${GIT_REPO}
Branch${GIT_BRANCH}
Docker Image${DOCKERHUB_USERNAME}/${DOCKER_IMAGE}:${params.GEMINI_DOCKER_TAG}
-

- Visit Pipeline Logs for more details. -

-

- Thanks,
- Jenkins -

-
- """, - to: "amitabhdevops2024@gmail.com", - from: "jenkins@example.com", - mimeType: 'text/html', - attachmentsPattern: '**/table-report.html' - ) - } -} -} - - diff --git a/kind/Jenkinsfile b/kind/Jenkinsfile new file mode 100644 index 0000000..df8599c --- /dev/null +++ b/kind/Jenkinsfile @@ -0,0 +1,37 @@ +pipeline { + agent { + label 'jenkins-jenkins-agent' + } + + environment { + MY_ENV = "production" + } + + stages { + stage('Clone Code') { + steps { + git url: 'https://github.com/harisamjad0158/dev-gemini-clone.git', branch: 'feat/kind' + } + } + + stage('Build') { + steps { + echo "Building application..." + sh 'echo Build done!' + } + } + + stage('Test') { + steps { + echo "Running tests..." + sh 'echo Tests passed!' + } + } + + stage('Deploy') { + steps { + echo "Deploying to ${MY_ENV} environment" + } + } + } +} diff --git a/kind/configmap.yml b/kind/configmap.yml index 9bb4d78..79f2ae2 100644 --- a/kind/configmap.yml +++ b/kind/configmap.yml @@ -4,4 +4,16 @@ metadata: name: gemini-config namespace: gemini-namespace data: - NEXTAUTH_URL: # Enter your NextAuth URL here(Domain name/URL) \ No newline at end of file + # Google OAuth Client ID (Public) + GOOGLE_ID: 843731093025-0iooes2k63ir68cn0bvvqlb2h220f9qc.apps.googleusercontent.com + + # WARNING: This should be in a SECRET! Only non-sensitive variables should be here. + # The username is EMBEDDED in this URI: alipeco90_db_user + MONGODB_URI: mongodb+srv://alipeco90_db_user:D7Xr4ExRbiavbE6K@cluster0.bnl24cv.mongodb.net/ + + # Application Base URL + NEXTAUTH_URL: https://72.61.159.174.nip.io + + # Explicitly define the application's database username, if needed by the code + # The previous name 'MONGODB_INITDB_ROOT_USERNAME' is typically used for initializing a local DB, not connecting to Atlas. + MONGODB_USERNAME: alipeco90_db_user diff --git a/kind/secrets.yml b/kind/secrets.yml index c3aa90d..bb48c2d 100644 --- a/kind/secrets.yml +++ b/kind/secrets.yml @@ -1,12 +1,15 @@ +# This is your new secrets.yml (using the 'stringData' field - RECOMMENDED) apiVersion: v1 kind: Secret metadata: name: gemini-secret - namespace: gemini-namespace + namespace: gemini-namespace type: Opaque -data: - GOOGLE_ID: # Enter your Google ID here in base64 encoded format - GOOGLE_SECRET: # Enter your Google secret here in base64 encoded format - NEXTAUTH_SECRET: # Enter your NextAuth secret here in base64 encoded format - NEXT_PUBLIC_API_KEY: # Enter your API key here in base64 encoded format - MONGODB_URI: # Enter your MongoDB URI here in base64 encoded format \ No newline at end of file +stringData: + # Look! No more Base64. Just paste the plain text values. + GOOGLE_ID: 843731093025-0iooes2k63ir68cn0bvvqlb2h220f9qc.apps.googleusercontent.com + GOOGLE_SECRET: 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 + NEXTAUTH_SECRET: Cst9orAxQM5h6BDwUnZiSEH4aw9juSMosDJ3x8LmdvQ= + NEXT_PUBLIC_API_KEY: AIzaSyB1e0MSZ4SC_m43jUisDft2p7lPcqem3v8 + MONGODB_URI: mongodb+srv://alipeco90_db_user:D7Xr4ExRbiavbE6K@cluster0.bnl24cv.mongodb.net/ + MONGODB_PASSWORD: D7Xr4ExRbiavbE6K diff --git a/kind/values.yml b/kind/values.yml new file mode 100644 index 0000000..5d92ec8 --- /dev/null +++ b/kind/values.yml @@ -0,0 +1,41 @@ +controller: + installPlugins: + - kubernetes + - workflow-aggregator + - git + - configuration-as-code + - credentials-binding + - blueocean + - pipeline-stage-view + - docker-plugin + - kubernetes-cli + JCasC: + enabled: true + configScripts: + welcome-message: | + jenkins: + systemMessage: "Jenkins running on KinD 🚀" + + resources: + requests: + cpu: "100m" + memory: "512Mi" + limits: + cpu: "500m" + memory: "1Gi" + + serviceType: NodePort # <-- Change this so you can access Jenkins via browser + nodePort: 32000 # Optional fixed port for http://localhost:32000 + +agent: + enabled: true + image: + repository: jenkins/inbound-agent + tag: alpine + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "200m" + memory: "512Mi"