Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CD Pipeline

on:
workflow_dispatch:
inputs:
docker_tag:
description: "Docker tag of the image built by CI"
required: true

env:
DOCKER_IMAGE: bankapp

jobs:
update-manifest-and-deploy:
name: "Update K8s Manifest & Push"
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: DevOps
token: ${{ secrets.GH_PAT }}

- name: Verify Docker image tag
run: |
echo "Docker tag received: ${{ github.event.inputs.docker_tag }}"

- name: Update Kubernetes deployment manifest
run: |
sed -i "s|${{ vars.DOCKERHUB_USER }}/${DOCKER_IMAGE}:.*|${{ vars.DOCKERHUB_USER }}/${DOCKER_IMAGE}:${{ github.event.inputs.docker_tag }}|g" \
kubernetes/bankapp-deployment.yaml

- name: Commit and push changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add kubernetes/bankapp-deployment.yaml
git diff --cached --quiet && echo "No changes to commit" && exit 0
git commit -m "Update K8s deployment image to ${{ vars.DOCKERHUB_USER }}/${DOCKER_IMAGE}:${{ github.event.inputs.docker_tag }}"
git push

- name: Send deployment notification
if: always()
uses: actions/github-script@v7
with:
script: |
const status = '${{ job.status }}';
const emoji = status === 'success' ? ':white_check_mark:' : ':x:';
const summary = `### ${emoji} BankApp Deployment Update\n` +
`- **Status**: ${status}\n` +
`- **Docker Tag**: ${{ github.event.inputs.docker_tag }}\n` +
`- **Run**: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
core.summary.addRaw(summary).write();
161 changes: 161 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: CI Pipeline

on:
push:
branches: [main, DevOps]
pull_request:
branches: [main, DevOps]
workflow_dispatch:
inputs:
docker_tag:
description: "Docker image tag"
required: false
default: "latest"

env:
DOCKER_IMAGE: bankapp
DOCKERHUB_USER: ${{ vars.DOCKERHUB_USER }}

jobs:
trivy-fs-scan:
name: "Trivy: Filesystem Scan"
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run Trivy filesystem scan
uses: aquasecurity/trivy-action@0.35.0
with:
scan-type: fs
scan-ref: .
format: table
severity: CRITICAL,HIGH

owasp-dependency-check:
name: "OWASP: Dependency Check"
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run OWASP Dependency-Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: bankapp
path: .
format: XML
args: --failOnCVSS 11

- name: Upload OWASP report
if: always()
uses: actions/upload-artifact@v4
with:
name: owasp-dependency-check-report
path: reports/

sonarqube-analysis:
name: "SonarQube: Code Analysis"
runs-on: ubuntu-latest
if: ${{ vars.SONAR_ENABLED == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v4
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=bankapp
-Dsonar.projectName=bankapp

- name: SonarQube Quality Gate
uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

docker-build-push:
name: "Docker: Build & Push"
runs-on: ubuntu-latest
needs: [trivy-fs-scan, owasp-dependency-check, sonarqube-analysis]
if: ${{ !failure() && !cancelled() }}
outputs:
docker_tag: ${{ steps.set-tag.outputs.tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Determine Docker tag
id: set-tag
run: |
if [ -n "${{ github.event.inputs.docker_tag }}" ]; then
TAG="${{ github.event.inputs.docker_tag }}"
else
TAG="${GITHUB_SHA::7}"
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Check Docker Hub credentials
id: docker-creds
run: |
if [ -n "$DOCKERHUB_USER" ] && [ -n "$DOCKERHUB_TOKEN" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
echo "::warning::Docker Hub credentials not configured — image will be built locally only"
fi
env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Hub
if: steps.docker-creds.outputs.available == 'true'
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ steps.docker-creds.outputs.available == 'true' }}
tags: |
${{ vars.DOCKERHUB_USER || 'local' }}/${{ env.DOCKER_IMAGE }}:${{ steps.set-tag.outputs.tag }}
${{ vars.DOCKERHUB_USER || 'local' }}/${{ env.DOCKER_IMAGE }}:latest

- name: Run Trivy image scan
if: steps.docker-creds.outputs.available == 'true'
uses: aquasecurity/trivy-action@0.35.0
with:
image-ref: ${{ vars.DOCKERHUB_USER }}/${{ env.DOCKER_IMAGE }}:${{ steps.set-tag.outputs.tag }}
format: table
severity: CRITICAL,HIGH

trigger-cd:
name: "Trigger CD Pipeline"
runs-on: ubuntu-latest
needs: docker-build-push
steps:
- name: Trigger CD workflow
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'cd.yml',
ref: context.ref,
inputs: {
docker_tag: '${{ needs.docker-build-push.outputs.docker_tag }}'
}
});
Loading