import re
from log_to_server import XbpLog
import time
import asyncio
async def parse_nextjs_logs(line, deployment_data):
patterns = {
r"Redeploying .*":
"Redeploying project",
r"Resetting local changes for (.+) \.\.\.":
lambda match: f"Resetting the git commit tree on {match.group(1)}",
r"Pulling latest changes for .*":
"Pulling new git changes onto local repository",
r"Already up to date\.":
"Successfully synced git to local repository",
r"Installing dependencies for .*":
"Installing dependencies for the project",
r"Done in (\d+\.\d+)s":
lambda match:
f"Successfully installed all dependencies in {match.group(1)} seconds",
r"Building .*":
"Initializing build of project",
r"Generating static pages \((\d+)/(\d+)\)":
lambda match:
f"Generating static pages: {match.group(1)}/{match.group(2)} completed",
r"Creating an optimized production build .*":
"Creating an optimized production build",
r"Finalizing page optimization \.\.\.":
"Finalizing the build process",
r"Collecting build traces \.\.\.":
"Collecting build traces and finalizing deployment",
r"Received GET request to generate thumbnail.*":
"Processing GET request to generate thumbnail",
r"sudo: .*":
"Executing command with elevated privileges",
r"▲ Next\.js (\d+\.\d+\.\d+)":
lambda match: f"Using Next.js version {match.group(1)}",
r"HEAD is now at ([a-f0-9]+)":
lambda match:
f"Successfully reset the git commit tree to {match.group(1)}",
r"○ \(Static\).*":
"Build completed successfully. Deployment will follow next.",
r"ƒ \(Dynamic\).*":
"Build completed successfully. Deployment will follow next.",
r"Stopping existing PM2 process for (.+) \.\.\.":
lambda match:
f"Replacing old build with the new build for {match.group(1)}",
r"\[PM2\] Applying action stopProcessId on app \[(.+)\]\(ids: \[ (\d+) \]\)":
lambda match:
f"Successfully killed old build for {match.group(1)} (Process ID: {match.group(2)})",
r"\[PM2\] \[(.+)\]\((\d+)\) ✓":
lambda match:
f"Successfully deployed {match.group(1)} (Process ID: {match.group(2)})",
}
for pattern, message in patterns.items():
match = re.search(pattern, line)
if match:
log_message = message(match) if callable(message) else message
runtime_version = match.group(
1) if "▲ Next.js" in pattern else "14.2.23"
log_data = {
"time":
int(time.time()),
"request":
None,
"http_status":
None,
"method":
None,
"payload":
None,
"status":
deployment_data.status,
"message":
log_message,
"deployment_id":
deployment_data.deployment_id,
"commit_id":
deployment_data.sha_short,
"project_id":
deployment_data.project_id,
"action":
"log_line_match",
"host":
"xylex.cloud",
"user_agent":
"xbp/nextjs",
"content_type":
None,
"repository_url":
f"https://github.com/{deployment_data.repository_owner}/{deployment_data.repository_name}",
"error":
False,
"runtime_version":
runtime_version,
"runtime":
"nodejs",
"framework":
"Next.js",
"total_pages":
int(match.group(2))
if "Generating static pages" in pattern else None,
"build_time":
None,
"time_start":
None,
"time_finish":
None,
"lint_time":
None,
"routes_sourcemap":
None,
"build_duration":
None,
"lint_duration":
None,
"routes_duration":
None,
"routes":
None,
"routes_count":
None,
"routes_time":
None,
}
try:
xbp_log = XbpLog(**log_data)
XbpLog.add_xbp_log_to_supabase(xbp_log)
print(f"Logged line to Supabase: {log_message}")
except Exception as e:
print(f"Failed to log line to Supabase: {str(e)}")
if "Successfully deployed" in log_message:
deployment_data.status = "success"
import httpx
async with httpx.AsyncClient() as client:
payload = {
"sha": deployment_data.sha,
"sha_short": deployment_data.sha_short,
"github_username": deployment_data.github_username,
"organization_name": deployment_data.organization_name,
"project_name": deployment_data.project_name,
"deployment_id": deployment_data.deployment_id,
"status": deployment_data.status,
"repository_name": deployment_data.repository_name,
"repository_owner": deployment_data.repository_owner,
"xbp_command": deployment_data.xbp_command,
"project_id": deployment_data.project_id,
}
response = await client.post(
"https://xbp.xylex.cloud/report-deployment-status",
json=payload)
print(
f"Report deployment status response: {response.status_code}, {response.text}"
)
await asyncio.sleep(10)
return True
break
return False