Skip to content

Commit b865274

Browse files
feat: add automatic CI/CD pipeline with GitHub Actions for Cloud Run deployment
1 parent 1a33383 commit b865274

File tree

3 files changed

+339
-7
lines changed

3 files changed

+339
-7
lines changed

.github/CICD_SETUP.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# CI/CD Setup for GDG Docs
2+
3+
## Overview
4+
This repository uses GitHub Actions for automatic deployment to Google Cloud Run. Every push to the `main` branch triggers a build, test, and deployment pipeline.
5+
6+
## Pipeline Workflow
7+
8+
### 1. Build and Test Job
9+
- ✅ Builds Docker image
10+
- ✅ Tests the container locally
11+
- ✅ Uploads image artifact for deployment
12+
13+
### 2. Deploy Job (only on main branch)
14+
- ✅ Authenticates with Google Cloud
15+
- ✅ Pushes image to Google Container Registry (GCR)
16+
- ✅ Deploys to Cloud Run
17+
- ✅ Provides deployment summary with URLs
18+
19+
## Setup Instructions
20+
21+
### Prerequisites
22+
1. Google Cloud Project with Cloud Run API enabled
23+
2. Service account with necessary permissions
24+
3. GitHub repository with Actions enabled
25+
26+
### Step 1: Create Google Cloud Service Account
27+
28+
```bash
29+
# Set your project ID
30+
export PROJECT_ID="erudite-marker-465011-c6"
31+
32+
# Create service account
33+
gcloud iam service-accounts create github-actions \
34+
--display-name="GitHub Actions CI/CD" \
35+
--project=$PROJECT_ID
36+
37+
# Grant necessary permissions
38+
gcloud projects add-iam-policy-binding $PROJECT_ID \
39+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
40+
--role="roles/run.admin"
41+
42+
gcloud projects add-iam-policy-binding $PROJECT_ID \
43+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
44+
--role="roles/storage.admin"
45+
46+
gcloud projects add-iam-policy-binding $PROJECT_ID \
47+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
48+
--role="roles/iam.serviceAccountUser"
49+
50+
# Create and download service account key
51+
gcloud iam service-accounts keys create github-actions-key.json \
52+
--iam-account=github-actions@${PROJECT_ID}.iam.gserviceaccount.com
53+
```
54+
55+
### Step 2: Add GitHub Secret
56+
57+
1. Go to your GitHub repository settings
58+
2. Navigate to **Settings → Secrets and variables → Actions**
59+
3. Click **New repository secret**
60+
4. Name: `GCP_SA_KEY`
61+
5. Value: Paste the entire contents of `github-actions-key.json`
62+
6. Click **Add secret**
63+
64+
**⚠️ Important:** Delete the `github-actions-key.json` file after adding it to GitHub:
65+
```bash
66+
rm github-actions-key.json
67+
```
68+
69+
### Step 3: Verify Workflow File
70+
71+
The workflow is already configured in `.github/workflows/ci.yml`. It will:
72+
- Trigger on every push to `main` branch
73+
- Build and test the Docker image
74+
- Deploy to Cloud Run (only on main branch pushes)
75+
76+
### Step 4: Test the Pipeline
77+
78+
1. Make a change to your repository
79+
2. Commit and push to `main` branch:
80+
```bash
81+
git add .
82+
git commit -m "Test CI/CD pipeline"
83+
git push origin main
84+
```
85+
3. Go to **Actions** tab in GitHub to see the workflow running
86+
4. Once complete, check the deployment summary for the service URL
87+
88+
## Environment Variables
89+
90+
The following environment variables are set automatically:
91+
- `PROJECT_ID`: Your Google Cloud project ID
92+
- `SERVICE_NAME`: Cloud Run service name (gdg-docs)
93+
- `REGION`: Deployment region (us-central1)
94+
- `IMAGE_NAME`: Full GCR image path
95+
96+
## Manual Deployment (Fallback)
97+
98+
If you need to deploy manually, you can still use:
99+
100+
```bash
101+
# Using gcloud CLI
102+
gcloud builds submit --config cloudbuild.yaml .
103+
104+
# Or using the deploy script
105+
bash deploy.sh
106+
```
107+
108+
## Monitoring Deployments
109+
110+
### View Deployment History
111+
```bash
112+
gcloud run revisions list --service=gdg-docs --region=us-central1
113+
```
114+
115+
### View Service Logs
116+
```bash
117+
gcloud run services logs read gdg-docs --region=us-central1
118+
```
119+
120+
### Check Service Status
121+
```bash
122+
gcloud run services describe gdg-docs --region=us-central1
123+
```
124+
125+
## Troubleshooting
126+
127+
### Build Fails
128+
- Check Docker build locally: `docker build -t gdg-docs .`
129+
- Review Dockerfile for errors
130+
- Check GitHub Actions logs for detailed error messages
131+
132+
### Authentication Fails
133+
- Verify `GCP_SA_KEY` secret is correctly set
134+
- Ensure service account has proper permissions
135+
- Check if APIs are enabled in Google Cloud
136+
137+
### Deployment Fails
138+
- Verify Cloud Run API is enabled
139+
- Check service account permissions
140+
- Review Cloud Run logs: `gcloud run services logs read gdg-docs`
141+
142+
### Container Doesn't Start
143+
- Test container locally: `docker run -p 8080:8080 gdg-docs`
144+
- Check port configuration (must be 8080)
145+
- Review container logs in Cloud Run console
146+
147+
## URLs
148+
149+
- **Cloud Run URL**: https://gdg-docs-426637717447.us-central1.run.app
150+
- **Custom Domain**: https://docs.gdgalgiers.dev
151+
- **GitHub Actions**: https://github.com/GDGAlgiers/gdg-docs/actions
152+
153+
## Security Notes
154+
155+
- ✅ Service account key is stored securely in GitHub Secrets
156+
- ✅ Only `main` branch deployments are automated
157+
- ✅ Pull requests are built and tested but not deployed
158+
- ✅ Service account has minimal required permissions
159+
160+
## Additional Resources
161+
162+
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
163+
- [Google Cloud Run Documentation](https://cloud.google.com/run/docs)
164+
- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/)

.github/workflows/ci.yml

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,111 @@
1-
name: Build and Deploy
1+
name: Build and Deploy to Cloud Run
22

33
on:
44
push:
55
branches: [ main ]
66
pull_request:
77
branches: [ main ]
88

9+
env:
10+
PROJECT_ID: erudite-marker-465011-c6
11+
SERVICE_NAME: gdg-docs
12+
REGION: us-central1
13+
IMAGE_NAME: gcr.io/erudite-marker-465011-c6/gdg-docs
14+
915
jobs:
10-
build:
16+
build-and-test:
1117
runs-on: ubuntu-latest
1218

1319
steps:
14-
- uses: actions/checkout@v4
20+
- name: Checkout code
21+
uses: actions/checkout@v4
1522

1623
- name: Build Docker image
17-
run: docker build -t gdg-docs:latest .
24+
run: docker build -t ${{ env.IMAGE_NAME }}:${{ github.sha }} -t ${{ env.IMAGE_NAME }}:latest .
1825

1926
- name: Test Docker image
2027
run: |
21-
docker run -d --name test-container -p 8080:8080 gdg-docs:latest
22-
sleep 10
28+
docker run -d --name test-container -p 8080:8080 ${{ env.IMAGE_NAME }}:latest
29+
sleep 15
2330
curl -f http://localhost:8080 || exit 1
24-
docker stop test-container
31+
docker stop test-container
32+
docker rm test-container
33+
34+
- name: Save image for deployment
35+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
36+
run: docker save ${{ env.IMAGE_NAME }}:${{ github.sha }} > gdg-docs.tar
37+
38+
- name: Upload image artifact
39+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
40+
uses: actions/upload-artifact@v4
41+
with:
42+
name: docker-image
43+
path: gdg-docs.tar
44+
retention-days: 1
45+
46+
deploy:
47+
needs: build-and-test
48+
runs-on: ubuntu-latest
49+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
50+
51+
permissions:
52+
contents: read
53+
id-token: write
54+
55+
steps:
56+
- name: Checkout code
57+
uses: actions/checkout@v4
58+
59+
- name: Download image artifact
60+
uses: actions/download-artifact@v4
61+
with:
62+
name: docker-image
63+
64+
- name: Load Docker image
65+
run: docker load < gdg-docs.tar
66+
67+
- name: Authenticate to Google Cloud
68+
uses: google-github-actions/auth@v2
69+
with:
70+
credentials_json: ${{ secrets.GCP_SA_KEY }}
71+
72+
- name: Set up Cloud SDK
73+
uses: google-github-actions/setup-gcloud@v2
74+
75+
- name: Configure Docker for GCR
76+
run: gcloud auth configure-docker
77+
78+
- name: Push image to GCR
79+
run: |
80+
docker push ${{ env.IMAGE_NAME }}:${{ github.sha }}
81+
docker push ${{ env.IMAGE_NAME }}:latest
82+
83+
- name: Deploy to Cloud Run
84+
run: |
85+
gcloud run deploy ${{ env.SERVICE_NAME }} \
86+
--image ${{ env.IMAGE_NAME }}:${{ github.sha }} \
87+
--region ${{ env.REGION }} \
88+
--platform managed \
89+
--allow-unauthenticated \
90+
--port 8080 \
91+
--memory 512Mi \
92+
--set-env-vars "ASTRO_SITE=https://docs.gdgalgiers.dev"
93+
94+
- name: Get service URL
95+
run: |
96+
SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} \
97+
--region ${{ env.REGION }} \
98+
--format 'value(status.url)')
99+
echo "Service deployed to: $SERVICE_URL"
100+
echo "SERVICE_URL=$SERVICE_URL" >> $GITHUB_ENV
101+
102+
- name: Create deployment summary
103+
run: |
104+
echo "## 🚀 Deployment Successful!" >> $GITHUB_STEP_SUMMARY
105+
echo "" >> $GITHUB_STEP_SUMMARY
106+
echo "**Service:** ${{ env.SERVICE_NAME }}" >> $GITHUB_STEP_SUMMARY
107+
echo "**Region:** ${{ env.REGION }}" >> $GITHUB_STEP_SUMMARY
108+
echo "**Image:** ${{ env.IMAGE_NAME }}:${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
109+
echo "**URL:** ${{ env.SERVICE_URL }}" >> $GITHUB_STEP_SUMMARY
110+
echo "" >> $GITHUB_STEP_SUMMARY
111+
echo "Custom domain: https://docs.gdgalgiers.dev" >> $GITHUB_STEP_SUMMARY

QUICK_CICD_SETUP.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Quick CI/CD Setup Guide
2+
3+
## What You Need to Do
4+
5+
### 1️⃣ Create Service Account Key
6+
7+
Run these commands in Google Cloud Shell or your terminal:
8+
9+
```bash
10+
# Set your project ID
11+
export PROJECT_ID="erudite-marker-465011-c6"
12+
13+
# Create service account
14+
gcloud iam service-accounts create github-actions \
15+
--display-name="GitHub Actions CI/CD" \
16+
--project=$PROJECT_ID
17+
18+
# Grant permissions
19+
gcloud projects add-iam-policy-binding $PROJECT_ID \
20+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
21+
--role="roles/run.admin"
22+
23+
gcloud projects add-iam-policy-binding $PROJECT_ID \
24+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
25+
--role="roles/storage.admin"
26+
27+
gcloud projects add-iam-policy-binding $PROJECT_ID \
28+
--member="serviceAccount:github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \
29+
--role="roles/iam.serviceAccountUser"
30+
31+
# Create key
32+
gcloud iam service-accounts keys create github-actions-key.json \
33+
--iam-account=github-actions@${PROJECT_ID}.iam.gserviceaccount.com
34+
35+
# Show the key (copy this entire output)
36+
cat github-actions-key.json
37+
```
38+
39+
### 2️⃣ Add Secret to GitHub
40+
41+
1. Go to: https://github.com/GDGAlgiers/gdg-docs/settings/secrets/actions
42+
2. Click **New repository secret**
43+
3. Name: `GCP_SA_KEY`
44+
4. Value: Paste the entire JSON from the previous step
45+
5. Click **Add secret**
46+
47+
### 3️⃣ Test It!
48+
49+
```bash
50+
# Make any small change
51+
echo "# CI/CD Test" >> README.md
52+
53+
# Commit and push
54+
git add .
55+
git commit -m "test: trigger CI/CD pipeline"
56+
git push origin main
57+
```
58+
59+
### 4️⃣ Watch It Deploy
60+
61+
Go to: https://github.com/GDGAlgiers/gdg-docs/actions
62+
63+
You'll see:
64+
- ✅ Build and test job running
65+
- ✅ Deploy job running (after tests pass)
66+
- ✅ Deployment summary with URLs
67+
68+
## That's It! 🎉
69+
70+
From now on, every push to `main` will automatically:
71+
1. Build your Docker image
72+
2. Test it
73+
3. Deploy to Cloud Run
74+
4. Show you the deployment URL
75+
76+
## Cleanup
77+
78+
After adding the key to GitHub, delete it locally:
79+
```bash
80+
rm github-actions-key.json
81+
```

0 commit comments

Comments
 (0)