Skip to content

Commit 670bba1

Browse files
committed
feat: Implement contact form API with email notifications
- Added email.js for handling email sending using SendGrid. - Created index.js to set up Express server and handle contact form submissions. - Implemented utils.js for common utility functions including response creation and logging. - Developed validation.js for validating contact form data using Joi. - Added integration tests for the contact form API in api.test.js. - Created unit tests for utility functions in utils.test.js and validation functions in validation.test.js. - Set up test environment configuration in setup.js. - Implemented rate limiting for the contact form submissions. - Added health check endpoint to monitor API status.
1 parent 6e84681 commit 670bba1

File tree

15 files changed

+2783
-2
lines changed

15 files changed

+2783
-2
lines changed

.env.example

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Environment Configuration
2+
# Copy this file to .env and fill in your actual values
3+
4+
# Google Cloud Platform
5+
GCP_PROJECT_ID=your-gcp-project-id
6+
7+
# Firestore Database
8+
FIRESTORE_COLLECTION=contact_submissions
9+
10+
# SendGrid Email Service
11+
SENDGRID_API_KEY=your-sendgrid-api-key
12+
13+
# Email Configuration
14+
ADMIN_EMAIL=[email protected]
15+
16+
COMPANY_NAME=Your Company Name
17+
18+
# CORS Configuration
19+
CORS_ORIGIN=https://yourwebsite.com
20+
21+
# Optional: Custom port for local development
22+
PORT=8080
23+
24+
# Optional: Log level (error, warn, info, debug)
25+
LOG_LEVEL=info

.github/workflows/deploy.yml

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
name: Deploy Contact Form API
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
11+
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
node-version: [18.x, 20.x]
20+
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Setup Node.js ${{ matrix.node-version }}
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: ${{ matrix.node-version }}
29+
cache: 'npm'
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
34+
- name: Run linting
35+
run: npm run lint
36+
37+
- name: Run unit tests
38+
run: npm run test:unit
39+
40+
- name: Run integration tests
41+
run: npm run test:integration
42+
43+
- name: Generate coverage report
44+
run: npm run test:coverage
45+
46+
- name: Upload coverage to Codecov
47+
uses: codecov/codecov-action@v3
48+
with:
49+
file: ./coverage/lcov.info
50+
flags: unittests
51+
name: codecov-umbrella
52+
53+
security-scan:
54+
runs-on: ubuntu-latest
55+
steps:
56+
- name: Checkout code
57+
uses: actions/checkout@v4
58+
59+
- name: Setup Node.js
60+
uses: actions/setup-node@v4
61+
with:
62+
node-version: '18'
63+
cache: 'npm'
64+
65+
- name: Install dependencies
66+
run: npm ci
67+
68+
- name: Run security audit
69+
run: npm audit --audit-level=moderate
70+
71+
- name: Run dependency check
72+
run: npx depcheck
73+
74+
deploy-staging:
75+
needs: [test, security-scan]
76+
runs-on: ubuntu-latest
77+
if: github.ref == 'refs/heads/develop'
78+
79+
steps:
80+
- name: Checkout code
81+
uses: actions/checkout@v4
82+
83+
- name: Setup Node.js
84+
uses: actions/setup-node@v4
85+
with:
86+
node-version: '18'
87+
cache: 'npm'
88+
89+
- name: Install dependencies
90+
run: npm ci
91+
92+
- name: Authenticate to Google Cloud
93+
uses: google-github-actions/auth@v2
94+
with:
95+
credentials_json: ${{ secrets.GCP_SA_KEY }}
96+
97+
- name: Setup Cloud SDK
98+
uses: google-github-actions/setup-gcloud@v2
99+
with:
100+
project_id: ${{ env.GCP_PROJECT_ID }}
101+
102+
- name: Deploy to staging
103+
run: |
104+
gcloud functions deploy contact-form-api-staging \
105+
--runtime nodejs18 \
106+
--trigger-http \
107+
--allow-unauthenticated \
108+
--source=. \
109+
--entry-point=contactFormHandler \
110+
--set-env-vars="GCP_PROJECT_ID=${{ env.GCP_PROJECT_ID }},SENDGRID_API_KEY=${{ secrets.SENDGRID_API_KEY }},ADMIN_EMAIL=${{ secrets.ADMIN_EMAIL }},FROM_EMAIL=${{ secrets.FROM_EMAIL }},COMPANY_NAME=${{ secrets.COMPANY_NAME }},CORS_ORIGIN=${{ secrets.CORS_ORIGIN_STAGING }}" \
111+
--max-instances=10 \
112+
--memory=256MB \
113+
--timeout=60s
114+
115+
deploy-production:
116+
needs: [test, security-scan]
117+
runs-on: ubuntu-latest
118+
if: github.ref == 'refs/heads/main'
119+
120+
steps:
121+
- name: Checkout code
122+
uses: actions/checkout@v4
123+
124+
- name: Setup Node.js
125+
uses: actions/setup-node@v4
126+
with:
127+
node-version: '18'
128+
cache: 'npm'
129+
130+
- name: Install dependencies
131+
run: npm ci
132+
133+
- name: Authenticate to Google Cloud
134+
uses: google-github-actions/auth@v2
135+
with:
136+
credentials_json: ${{ secrets.GCP_SA_KEY }}
137+
138+
- name: Setup Cloud SDK
139+
uses: google-github-actions/setup-gcloud@v2
140+
with:
141+
project_id: ${{ env.GCP_PROJECT_ID }}
142+
143+
- name: Deploy to production
144+
run: |
145+
gcloud functions deploy contact-form-api \
146+
--runtime nodejs18 \
147+
--trigger-http \
148+
--allow-unauthenticated \
149+
--source=. \
150+
--entry-point=contactFormHandler \
151+
--set-env-vars="GCP_PROJECT_ID=${{ env.GCP_PROJECT_ID }},SENDGRID_API_KEY=${{ secrets.SENDGRID_API_KEY }},ADMIN_EMAIL=${{ secrets.ADMIN_EMAIL }},FROM_EMAIL=${{ secrets.FROM_EMAIL }},COMPANY_NAME=${{ secrets.COMPANY_NAME }},CORS_ORIGIN=${{ secrets.CORS_ORIGIN }}" \
152+
--max-instances=50 \
153+
--memory=512MB \
154+
--timeout=60s
155+
156+
- name: Create GitHub Release
157+
if: success()
158+
uses: actions/create-release@v1
159+
env:
160+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
161+
with:
162+
tag_name: v${{ github.run_number }}
163+
release_name: Release v${{ github.run_number }}
164+
body: |
165+
Automated release of contact form API
166+
- Deployed to production
167+
- All tests passed
168+
- Security scan completed
169+
draft: false
170+
prerelease: false

.gitignore

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Dependencies
2+
node_modules/
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
7+
# Environment variables
8+
.env
9+
.env.local
10+
.env.development.local
11+
.env.test.local
12+
.env.production.local
13+
14+
# Google Cloud
15+
.gcloudignore
16+
service-account-key.json
17+
*.json
18+
19+
# Logs
20+
logs
21+
*.log
22+
23+
# Runtime data
24+
pids
25+
*.pid
26+
*.seed
27+
*.pid.lock
28+
29+
# Coverage directory used by tools like istanbul
30+
coverage/
31+
*.lcov
32+
33+
# nyc test coverage
34+
.nyc_output
35+
36+
# Test results
37+
test-results/
38+
junit.xml
39+
40+
# IDE files
41+
.vscode/
42+
.idea/
43+
*.swp
44+
*.swo
45+
*~
46+
47+
# OS generated files
48+
.DS_Store
49+
.DS_Store?
50+
._*
51+
.Spotlight-V100
52+
.Trashes
53+
ehthumbs.db
54+
Thumbs.db
55+
56+
# Terraform
57+
*.tfstate
58+
*.tfstate.*
59+
.terraform/
60+
.terraform.lock.hcl
61+
62+
# Build outputs
63+
dist/
64+
build/
65+
out/
66+
67+
# Temporary files
68+
tmp/
69+
temp/

0 commit comments

Comments
 (0)