bug fix and some icons changes
This commit is contained in:
@@ -1,10 +1,27 @@
|
||||
import { json } from '@remix-run/node';
|
||||
import type { ActionFunction } from '@remix-run/node';
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
interface UpdateRequestBody {
|
||||
branch: string;
|
||||
}
|
||||
|
||||
interface UpdateProgress {
|
||||
stage: 'fetch' | 'pull' | 'install' | 'build' | 'complete';
|
||||
message: string;
|
||||
progress?: number;
|
||||
error?: string;
|
||||
details?: {
|
||||
changedFiles?: string[];
|
||||
additions?: number;
|
||||
deletions?: number;
|
||||
commitMessages?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
if (request.method !== 'POST') {
|
||||
return json({ error: 'Method not allowed' }, { status: 405 });
|
||||
@@ -13,24 +30,135 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
try {
|
||||
const body = await request.json();
|
||||
|
||||
// Type guard to check if body has the correct shape
|
||||
if (!body || typeof body !== 'object' || !('branch' in body) || typeof body.branch !== 'string') {
|
||||
return json({ error: 'Invalid request body: branch is required and must be a string' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { branch } = body as UpdateRequestBody;
|
||||
|
||||
// Instead of direct Git operations, we'll return instructions
|
||||
return json({
|
||||
success: true,
|
||||
message: 'Please update manually using the following steps:',
|
||||
instructions: [
|
||||
`1. git fetch origin ${branch}`,
|
||||
`2. git pull origin ${branch}`,
|
||||
'3. pnpm install',
|
||||
'4. pnpm build',
|
||||
'5. Restart the application',
|
||||
],
|
||||
// Create a ReadableStream to send progress updates
|
||||
const stream = new ReadableStream({
|
||||
async start(controller) {
|
||||
const encoder = new TextEncoder();
|
||||
const sendProgress = (update: UpdateProgress) => {
|
||||
controller.enqueue(encoder.encode(JSON.stringify(update) + '\n'));
|
||||
};
|
||||
|
||||
try {
|
||||
// Fetch stage
|
||||
sendProgress({
|
||||
stage: 'fetch',
|
||||
message: 'Fetching latest changes...',
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
// Get current commit hash
|
||||
const { stdout: currentCommit } = await execAsync('git rev-parse HEAD');
|
||||
|
||||
// Fetch changes
|
||||
await execAsync('git fetch origin');
|
||||
|
||||
// Get list of changed files
|
||||
const { stdout: diffOutput } = await execAsync(`git diff --name-status origin/${branch}`);
|
||||
const changedFiles = diffOutput
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
const [status, file] = line.split('\t');
|
||||
return `${status === 'M' ? 'Modified' : status === 'A' ? 'Added' : 'Deleted'}: ${file}`;
|
||||
});
|
||||
|
||||
// Get commit messages
|
||||
const { stdout: logOutput } = await execAsync(`git log --oneline ${currentCommit.trim()}..origin/${branch}`);
|
||||
const commitMessages = logOutput.split('\n').filter(Boolean);
|
||||
|
||||
// Get diff stats
|
||||
const { stdout: diffStats } = await execAsync(`git diff --shortstat origin/${branch}`);
|
||||
const stats = diffStats.match(
|
||||
/(\d+) files? changed(?:, (\d+) insertions?\\(\\+\\))?(?:, (\d+) deletions?\\(-\\))?/,
|
||||
);
|
||||
|
||||
sendProgress({
|
||||
stage: 'fetch',
|
||||
message: 'Changes detected',
|
||||
progress: 100,
|
||||
details: {
|
||||
changedFiles,
|
||||
additions: stats?.[2] ? parseInt(stats[2]) : 0,
|
||||
deletions: stats?.[3] ? parseInt(stats[3]) : 0,
|
||||
commitMessages,
|
||||
},
|
||||
});
|
||||
|
||||
// Pull stage
|
||||
sendProgress({
|
||||
stage: 'pull',
|
||||
message: `Pulling changes from ${branch}...`,
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
await execAsync(`git pull origin ${branch}`);
|
||||
|
||||
sendProgress({
|
||||
stage: 'pull',
|
||||
message: 'Changes pulled successfully',
|
||||
progress: 100,
|
||||
});
|
||||
|
||||
// Install stage
|
||||
sendProgress({
|
||||
stage: 'install',
|
||||
message: 'Installing dependencies...',
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
await execAsync('pnpm install');
|
||||
|
||||
sendProgress({
|
||||
stage: 'install',
|
||||
message: 'Dependencies installed successfully',
|
||||
progress: 100,
|
||||
});
|
||||
|
||||
// Build stage
|
||||
sendProgress({
|
||||
stage: 'build',
|
||||
message: 'Building application...',
|
||||
progress: 0,
|
||||
});
|
||||
|
||||
await execAsync('pnpm build');
|
||||
|
||||
sendProgress({
|
||||
stage: 'build',
|
||||
message: 'Build completed successfully',
|
||||
progress: 100,
|
||||
});
|
||||
|
||||
// Complete
|
||||
sendProgress({
|
||||
stage: 'complete',
|
||||
message: 'Update completed successfully! Click Restart to apply changes.',
|
||||
progress: 100,
|
||||
});
|
||||
} catch (error) {
|
||||
sendProgress({
|
||||
stage: 'complete',
|
||||
message: 'Update failed',
|
||||
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
||||
});
|
||||
} finally {
|
||||
controller.close();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(stream, {
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
Connection: 'keep-alive',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Update preparation failed:', error);
|
||||
|
||||
Reference in New Issue
Block a user