Skip to content

Commit c7b2890

Browse files
authored
Merge pull request #235 from codeunia-dev/fix/ci-cd-pipeline-and-performance-optimizations
Fix/ci cd pipeline and performance optimizations
2 parents 2fc5087 + 8b768f7 commit c7b2890

10 files changed

Lines changed: 113 additions & 26 deletions

File tree

.github/workflows/ci-cd.yml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,16 @@ jobs:
327327
- name: Deploy to Vercel (Staging)
328328
id: deploy-staging
329329
run: |
330-
DEPLOYMENT_URL=$(vercel deploy --token ${{ secrets.VERCEL_TOKEN }} --yes)
330+
echo "🚀 Deploying to Vercel staging..."
331+
DEPLOYMENT_URL=$(vercel deploy --token ${{ secrets.VERCEL_TOKEN }} --yes 2>&1 | grep -o 'https://[^[:space:]]*' | head -1)
332+
333+
if [ -z "$DEPLOYMENT_URL" ]; then
334+
echo "❌ Failed to get deployment URL from Vercel output"
335+
echo "Vercel output:"
336+
vercel deploy --token ${{ secrets.VERCEL_TOKEN }} --yes
337+
exit 1
338+
fi
339+
331340
echo "deployment-url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
332341
echo "🚀 Staging deployment URL: $DEPLOYMENT_URL"
333342
env:
@@ -453,7 +462,16 @@ jobs:
453462
- name: Deploy to Vercel (Production)
454463
id: deploy-production
455464
run: |
456-
DEPLOYMENT_URL=$(vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }} --yes)
465+
echo "🚀 Deploying to Vercel production..."
466+
DEPLOYMENT_URL=$(vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }} --yes 2>&1 | grep -o 'https://[^[:space:]]*' | head -1)
467+
468+
if [ -z "$DEPLOYMENT_URL" ]; then
469+
echo "❌ Failed to get deployment URL from Vercel output"
470+
echo "Vercel output:"
471+
vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }} --yes
472+
exit 1
473+
fi
474+
457475
echo "deployment-url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
458476
echo "🚀 Production deployment URL: $DEPLOYMENT_URL"
459477
env:
@@ -609,6 +627,10 @@ jobs:
609627
if [ -z "$DEPLOYMENT_URL" ]; then
610628
echo "❌ Deployment URL is empty, using fallback URL"
611629
DEPLOYMENT_URL="${{ secrets.PRODUCTION_URL }}"
630+
if [ -z "$DEPLOYMENT_URL" ]; then
631+
echo "❌ No fallback URL available, using default"
632+
DEPLOYMENT_URL="https://codeunia.com"
633+
fi
612634
fi
613635
614636
# Ensure URL has protocol
@@ -685,6 +707,9 @@ jobs:
685707
DEPLOYMENT_URL="${{ needs.deploy-production.outputs.deployment-url }}"
686708
if [ -z "$DEPLOYMENT_URL" ]; then
687709
DEPLOYMENT_URL="${{ secrets.PRODUCTION_URL }}"
710+
if [ -z "$DEPLOYMENT_URL" ]; then
711+
DEPLOYMENT_URL="https://codeunia.com"
712+
fi
688713
fi
689714
690715
echo "Testing URL: $DEPLOYMENT_URL"
@@ -758,6 +783,10 @@ jobs:
758783
if [ -z "$DEPLOYMENT_URL" ]; then
759784
echo "❌ Staging deployment URL is empty, using fallback URL"
760785
DEPLOYMENT_URL="${{ secrets.STAGING_URL }}"
786+
if [ -z "$DEPLOYMENT_URL" ]; then
787+
echo "❌ No fallback URL available, using default"
788+
DEPLOYMENT_URL="https://codeunia.com"
789+
fi
761790
fi
762791
763792
# Ensure URL has protocol
@@ -828,6 +857,9 @@ jobs:
828857
DEPLOYMENT_URL="${{ needs.deploy-staging.outputs.deployment-url }}"
829858
if [ -z "$DEPLOYMENT_URL" ]; then
830859
DEPLOYMENT_URL="${{ secrets.STAGING_URL }}"
860+
if [ -z "$DEPLOYMENT_URL" ]; then
861+
DEPLOYMENT_URL="https://codeunia.com"
862+
fi
831863
fi
832864
833865
echo "Testing URL: $DEPLOYMENT_URL"

app/api/admin-page-views/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ export async function GET() {
1515
return NextResponse.json({ error: error.message }, { status: 500 });
1616
}
1717

18-
const totalViews = (data || []).reduce((sum: number, blog: any) => sum + (blog.views || 0), 0);
18+
const totalViews = (data || []).reduce((sum: number, blog: Record<string, unknown>) => sum + (blog.views as number || 0), 0);
1919
return NextResponse.json({ totalViews });
2020
}

app/api/admin/tests/[id]/results/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ export async function GET(
8484
const stats = {
8585
totalRegistrations: registrations?.length || 0,
8686
totalAttempts: allAttempts?.length || 0,
87-
passedAttempts: allAttempts?.filter((a: any) => a.passed).length || 0,
88-
averageScore: allAttempts ? allAttempts.reduce((sum: number, a: any) => sum + (a.score || 0), 0) / allAttempts.length : 0,
89-
averageTime: allAttempts ? allAttempts.reduce((sum: number, a: any) => sum + (a.time_taken_minutes || 0), 0) / allAttempts.length : 0
87+
passedAttempts: allAttempts?.filter((a: Record<string, unknown>) => a.passed).length || 0,
88+
averageScore: allAttempts ? allAttempts.reduce((sum: number, a: Record<string, unknown>) => sum + (a.score as number || 0), 0) / allAttempts.length : 0,
89+
averageTime: allAttempts ? allAttempts.reduce((sum: number, a: Record<string, unknown>) => sum + (a.time_taken_minutes as number || 0), 0) / allAttempts.length : 0
9090
};
9191

9292
return NextResponse.json({

app/api/admin/users/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const GET = withRateLimit(
4545
throw new Error(`Failed to fetch users: ${error.message}`);
4646
}
4747

48-
const users = profiles?.map((profile: any) => ({
48+
const users = profiles?.map((profile: Record<string, unknown>) => ({
4949
id: profile.id,
5050
email: profile.email || '',
5151
username: profile.username || '',
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
3+
export const runtime = 'nodejs'
4+
5+
export async function POST(request: NextRequest) {
6+
try {
7+
const body = await request.json()
8+
9+
// Validate request body
10+
if (!body || !Array.isArray(body.metrics)) {
11+
return NextResponse.json(
12+
{ error: 'Invalid request body. Expected { metrics: [] }' },
13+
{ status: 400 }
14+
)
15+
}
16+
17+
const { metrics } = body
18+
19+
// Process performance metrics
20+
const processedMetrics = metrics.map((metric: Record<string, unknown>) => ({
21+
...metric,
22+
timestamp: new Date().toISOString(),
23+
processed: true
24+
}))
25+
26+
// Log metrics for monitoring
27+
console.log(`📊 Performance metrics batch received: ${processedMetrics.length} metrics`)
28+
29+
// In a real implementation, you would:
30+
// 1. Store metrics in database
31+
// 2. Send to external monitoring service
32+
// 3. Trigger alerts if thresholds exceeded
33+
34+
return NextResponse.json({
35+
success: true,
36+
processed: processedMetrics.length,
37+
message: 'Performance metrics processed successfully'
38+
})
39+
40+
} catch (error) {
41+
console.error('Error processing performance metrics:', error)
42+
return NextResponse.json(
43+
{ error: 'Failed to process performance metrics' },
44+
{ status: 500 }
45+
)
46+
}
47+
}
48+
49+
export async function GET() {
50+
return NextResponse.json({
51+
message: 'Performance analytics endpoint is active',
52+
methods: ['POST'],
53+
status: 'healthy'
54+
})
55+
}

app/api/internships/my-applications/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function GET() {
2626
return NextResponse.json({ error: error.message }, { status: 500 })
2727
}
2828

29-
const ids = (data || []).map((r: any) => r.internship_id)
29+
const ids = (data || []).map((r: Record<string, unknown>) => r.internship_id)
3030
const response = NextResponse.json({ appliedIds: ids })
3131

3232
// Prevent caching to ensure fresh data

lib/monitoring/health-checks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ export class HealthChecker {
296296
message: `Database tables check failed: ${tablesError.message}`
297297
});
298298
} else {
299-
const existingTables = tables?.map((t: any) => t.table_name) || [];
299+
const existingTables = tables?.map((t: Record<string, unknown>) => t.table_name) || [];
300300
const requiredTables = ['profiles', 'user_points', 'user_activity_log'];
301301
const missingTables = requiredTables.filter(table => !existingTables.includes(table));
302302

lib/security/csp-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function getCSPConfig(request: NextRequest): CSPConfig {
4545
"style-src 'self' 'nonce-" + nonce + "' 'unsafe-inline' https://fonts.googleapis.com",
4646
"font-src 'self' https://fonts.gstatic.com",
4747
"img-src 'self' data: https: blob:",
48-
"connect-src 'self' https://*.supabase.co https://*.vercel.app wss://*.supabase.co https://api.razorpay.com",
48+
"connect-src 'self' https://*.supabase.co https://*.vercel.app wss://*.supabase.co https://api.razorpay.com https://codeunia.com https://www.codeunia.com",
4949
"frame-src 'self' https://checkout.razorpay.com",
5050
"object-src 'none'",
5151
"base-uri 'self'",
@@ -81,7 +81,7 @@ export function getDevelopmentCSP(): string {
8181
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
8282
"font-src 'self' https://fonts.gstatic.com",
8383
"img-src 'self' data: https: blob:",
84-
"connect-src 'self' https://*.supabase.co https://*.vercel.app wss://*.supabase.co https://api.razorpay.com",
84+
"connect-src 'self' https://*.supabase.co https://*.vercel.app wss://*.supabase.co https://api.razorpay.com https://codeunia.com https://www.codeunia.com",
8585
"frame-src 'self' https://checkout.razorpay.com",
8686
"object-src 'none'",
8787
"base-uri 'self'",

lib/services/audit-logger.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,16 @@ export class AuditLogger {
167167
}
168168

169169
// Transform the data to include admin name and email
170-
const logs = data?.map((log: any) => ({
171-
id: log.id,
172-
admin_id: log.admin_id,
173-
action_type: log.action_type,
174-
target_resource: log.target_resource,
175-
target_id: log.target_id,
176-
metadata: log.metadata,
177-
ip_address: log.ip_address,
178-
user_agent: log.user_agent,
179-
created_at: log.created_at,
170+
const logs = data?.map((log: Record<string, unknown>) => ({
171+
id: log.id as string,
172+
admin_id: log.admin_id as string,
173+
action_type: log.action_type as AuditActionType,
174+
target_resource: log.target_resource as string,
175+
target_id: log.target_id as string | undefined,
176+
metadata: log.metadata as Record<string, unknown>,
177+
ip_address: log.ip_address as string | undefined,
178+
user_agent: log.user_agent as string | undefined,
179+
created_at: log.created_at as string,
180180
admin_name: 'Admin User', // Will be populated when profiles table is available
181181
admin_email: 'admin@codeunia.com' // Will be populated when profiles table is available
182182
})) || [];
@@ -231,8 +231,8 @@ export class AuditLogger {
231231
.gte('created_at', startDate.toISOString());
232232

233233
const actionsByTypeMap: Record<string, number> = {};
234-
actionsByType?.forEach((action: any) => {
235-
actionsByTypeMap[action.action_type] = (actionsByTypeMap[action.action_type] || 0) + 1;
234+
actionsByType?.forEach((action: Record<string, unknown>) => {
235+
actionsByTypeMap[action.action_type as string] = (actionsByTypeMap[action.action_type as string] || 0) + 1;
236236
});
237237

238238
// Get actions by admin
@@ -242,8 +242,8 @@ export class AuditLogger {
242242
.gte('created_at', startDate.toISOString());
243243

244244
const adminCounts: Record<string, { name: string; count: number }> = {};
245-
actionsByAdmin?.forEach((action: any) => {
246-
const adminId = action.admin_id;
245+
actionsByAdmin?.forEach((action: Record<string, unknown>) => {
246+
const adminId = action.admin_id as string;
247247
const adminName = 'Admin User'; // Will be populated when profiles table is available
248248

249249
if (!adminCounts[adminId]) {

next.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const nextConfig: NextConfig = {
1717
return buildId
1818
},
1919

20-
// Simplified webpack config for better Vercel compatibility
20+
// Minimal webpack config for better Vercel compatibility
2121
webpack: (config, { isServer }) => {
2222
// Only add essential configurations
2323
if (!isServer) {

0 commit comments

Comments
 (0)