Skip to content

Commit 1444034

Browse files
Merge branch 'main' into ci-cd-with-github-action
2 parents 803f410 + 3ac293f commit 1444034

21 files changed

+2106
-85
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ jobs:
1515
distribution: 'temurin'
1616
java-version: '21'
1717
- name: Maven Clean Verify
18-
run: mvn -B -ntp clean verify
18+
run: mvn -B -ntp clean verify

.github/workflows/deploy.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Deploy Workflow
2+
on:
3+
push:
4+
branches:
5+
- main
6+
workflow_dispatch:
7+
inputs:
8+
build_number:
9+
description: "The build number to deploy (optional)"
10+
required: false
11+
type: string
12+
jobs:
13+
build-and-deploy:
14+
runs-on: ubuntu-latest
15+
env:
16+
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
17+
DOCKER_IMAGE_NAME: product-service
18+
DOCKER_COMPOSE_APP_SERVICE_NAME: product-service
19+
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
20+
EC2_SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
21+
EC2_PUBLIC_IP_ADDRESS: ${{ secrets.EC2_PUBLIC_IP_ADDRESS }}
22+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
23+
24+
steps:
25+
- name: Checkout
26+
if: ${{ github.event.inputs.build_number == '' }}
27+
uses: actions/checkout@v4
28+
- name: Send slack message with github commit url
29+
run: >
30+
curl -X POST -H 'Content-type: application/json'
31+
--data '{"text":":rocket: Deployment started for commit: ${{ github.event.head_commit.message }} - https://github.com/${{ github.repository }}/commit/${{ github.sha }}"}'
32+
${{ env.SLACK_WEBHOOK_URL }}
33+
- name: JDK
34+
if: ${{ github.event.inputs.build_number == '' }}
35+
uses: actions/setup-java@v4
36+
with:
37+
distribution: 'temurin'
38+
java-version: '21'
39+
- name: Generate Build Number
40+
run: |
41+
if [ -n "${{ github.event.inputs.build_number }}" ]; then
42+
BUILD_NUMBER=${{ github.event.inputs.build_number }}
43+
echo "using provided build number: $BUILD_NUMBER"
44+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":package: Using provided build number: $BUILD_NUMBER\"}" ${{ env.SLACK_WEBHOOK_URL }}
45+
else
46+
BUILD_NUMBER=$(date +'%d%m%Y%H%M%S')
47+
echo "using generated build number: $BUILD_NUMBER"
48+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":gear: Generated new build number: $BUILD_NUMBER\"}" ${{ env.SLACK_WEBHOOK_URL }}
49+
fi
50+
echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
51+
- name: Login to Docker Hub
52+
uses: docker/login-action@v3
53+
with:
54+
username: ${{ env.DOCKER_USERNAME }}
55+
password: ${{ env.DOCKER_PASSWORD }}
56+
- name: Check if provided docker image exists
57+
if: ${{ github.event.inputs.build_number != '' }}
58+
run: |
59+
IMAGE="${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:$BUILD_NUMBER"
60+
echo "checking if $IMAGE exists"
61+
if ! docker manifest inspect "$IMAGE" > /dev/null 2>&1; then
62+
echo "provided image $IMAGE does not exist. exiting..."
63+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":x: :warning: Provided image $IMAGE does not exist! Exiting deployment...\"}" ${{ env.SLACK_WEBHOOK_URL }}
64+
exit 1
65+
fi
66+
echo "provided image $IMAGE exists ✅"
67+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":white_check_mark: Image $IMAGE exists and ready for deployment\"}" ${{ env.SLACK_WEBHOOK_URL }}
68+
echo "IMAGE=$IMAGE" >> $GITHUB_ENV
69+
70+
- name: Maven Clean Verify
71+
if: ${{ github.event.inputs.build_number == '' }}
72+
run: |
73+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":hammer_and_wrench: Building and deploying to Docker Hub...\"}" ${{ env.SLACK_WEBHOOK_URL }}
74+
mvn -B -ntp clean verify jib:build -Ddocker.image.tag=$BUILD_NUMBER
75+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":white_check_mark: Successfully built and pushed to Docker Hub\"}" ${{ env.SLACK_WEBHOOK_URL }}
76+
- name: Setup SSH Agent
77+
uses: webfactory/ssh-agent@v0.9.0
78+
with:
79+
ssh-private-key: ${{ env.EC2_SSH_PRIVATE_KEY }}
80+
- name: SSH To EC2 and Deploy
81+
run: |
82+
curl -X POST -H 'Content-type: application/json' --data '{"text":":cloud: Deploying to AWS EC2..."}' ${{ env.SLACK_WEBHOOK_URL }}
83+
ssh -o StrictHostKeyChecking=no ec2-user@$EC2_PUBLIC_IP_ADDRESS << EOF
84+
cd ~
85+
sed -i 's|image: '"$DOCKER_USERNAME"'/'"$DOCKER_IMAGE_NAME"':.*$|image: '"$DOCKER_USERNAME"'/'"$DOCKER_IMAGE_NAME"':'"$BUILD_NUMBER"'|' docker-compose.yml
86+
docker-compose pull
87+
docker-compose up -d '$DOCKER_COMPOSE_APP_SERVICE_NAME'
88+
docker image prune -f
89+
docker ps
90+
echo "$BUILD_NUMBER" > build-number.txt
91+
EOF
92+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":tada: Successfully deployed to AWS EC2\"}" ${{ env.SLACK_WEBHOOK_URL }}
93+
- name: Send slack message with status
94+
if: always()
95+
run: |
96+
if [ "${{ job.status }}" == "success" ]; then
97+
EMOJI=":tada:"
98+
MESSAGE="Deployment completed successfully!"
99+
else
100+
EMOJI=":x:"
101+
MESSAGE="Deployment failed!"
102+
fi
103+
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\"$EMOJI $MESSAGE - Job status: ${{ job.status }}\"}" ${{ env.SLACK_WEBHOOK_URL }}

AWS_DEPLOYMENT_CHECKLIST.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Quick AWS Deployment Checklist
2+
3+
## ✅ What You Need to Do in AWS Console
4+
5+
### 1. Create S3 Bucket
6+
- Go to **S3****Create bucket**
7+
- Name: `yourcompany-product-images-prod` (unique name)
8+
- Region: Same as your EC2 (e.g., `us-east-1`)
9+
- Encryption: Enable (SSE-S3)
10+
- **Save bucket name**
11+
12+
### 2. Create IAM Policy
13+
- Go to **IAM****Policies****Create policy**
14+
- Use JSON tab, paste:
15+
```json
16+
{
17+
"Version": "2012-10-17",
18+
"Statement": [
19+
{
20+
"Effect": "Allow",
21+
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:HeadObject"],
22+
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
23+
},
24+
{
25+
"Effect": "Allow",
26+
"Action": ["s3:ListBucket"],
27+
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
28+
}
29+
]
30+
}
31+
```
32+
- Replace `YOUR-BUCKET-NAME` with your bucket name
33+
- Name: `ProductServiceS3Policy`
34+
35+
### 3. Create IAM Role (Recommended)
36+
- Go to **IAM****Roles****Create role**
37+
- Select **EC2****Next**
38+
- Attach `ProductServiceS3Policy`**Next**
39+
- Name: `EC2-S3-Access-Role`**Create role**
40+
41+
### 4. Attach Role to EC2
42+
- Go to **EC2****Instances**
43+
- Select your instance → **Actions****Security****Modify IAM role**
44+
- Select `EC2-S3-Access-Role`**Update**
45+
46+
### 5. Update Application Configuration
47+
48+
Create `application-prod.properties` or use environment variables:
49+
50+
```properties
51+
aws.region=us-east-1
52+
aws.s3.bucket=your-bucket-name-here
53+
aws.s3.endpoint-override=
54+
aws.s3.path-style-enabled=false
55+
aws.access-key-id=
56+
aws.secret-access-key=
57+
```
58+
59+
**Note**: Leave access keys empty if using IAM role (recommended)
60+
61+
### 6. Deploy Application
62+
```bash
63+
# Build
64+
mvn clean package
65+
66+
# Copy to EC2
67+
scp -i key.pem target/product-service.jar ec2-user@your-ec2-ip:~/app/
68+
69+
# SSH into EC2
70+
ssh -i key.pem ec2-user@your-ec2-ip
71+
72+
# Run with production config
73+
cd ~/app
74+
java -jar product-service.jar --spring.config.location=application-prod.properties
75+
```
76+
77+
## 🔐 Alternative: Using Access Keys (Less Secure)
78+
79+
If not using IAM role, create IAM user:
80+
- **IAM****Users****Create user**
81+
- Attach `ProductServiceS3Policy`
82+
- Create access key → **Save keys securely**
83+
- Set environment variables on EC2:
84+
```bash
85+
export AWS_ACCESS_KEY_ID=your-key-id
86+
export AWS_SECRET_ACCESS_KEY=your-secret-key
87+
```
88+
89+
---
90+
91+
**See `AWS_DEPLOYMENT_GUIDE.md` for detailed step-by-step instructions.**
92+

0 commit comments

Comments
 (0)