mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
feat: add Docker container launch option and update process handling
- Introduced a new option to launch the application in a Docker container (Isolated Mode) from the main menu. - Added checks for the ANTHROPIC_API_KEY environment variable to ensure proper API functionality. - Updated process management to include Docker, allowing for better cleanup and handling of spawned processes. - Enhanced user prompts and logging for improved clarity during the launch process.
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
39
dev.mjs
39
dev.mjs
@@ -42,6 +42,7 @@ const processes = {
|
||||
server: null,
|
||||
web: null,
|
||||
electron: null,
|
||||
docker: null,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -96,7 +97,7 @@ async function main() {
|
||||
|
||||
// Prompt for choice
|
||||
while (true) {
|
||||
const choice = await prompt('Enter your choice (1 or 2): ');
|
||||
const choice = await prompt('Enter your choice (1, 2, or 3): ');
|
||||
|
||||
if (choice === '1') {
|
||||
console.log('');
|
||||
@@ -167,9 +168,43 @@ async function main() {
|
||||
processes.electron.on('close', resolve);
|
||||
});
|
||||
|
||||
break;
|
||||
} else if (choice === '3') {
|
||||
console.log('');
|
||||
log('Launching Docker Container (Isolated Mode)...', 'blue');
|
||||
log('Building and starting Docker containers...', 'yellow');
|
||||
console.log('');
|
||||
|
||||
// Check if ANTHROPIC_API_KEY is set
|
||||
if (!process.env.ANTHROPIC_API_KEY) {
|
||||
log('Warning: ANTHROPIC_API_KEY environment variable is not set.', 'yellow');
|
||||
log('The server will require an API key to function.', 'yellow');
|
||||
log('Set it with: export ANTHROPIC_API_KEY=your-key', 'yellow');
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Build and start containers with docker-compose
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up', '--build'], {
|
||||
stdio: 'inherit',
|
||||
cwd: __dirname,
|
||||
env: {
|
||||
...process.env,
|
||||
},
|
||||
});
|
||||
|
||||
log('Docker containers starting...', 'blue');
|
||||
log('UI will be available at: http://localhost:3007', 'green');
|
||||
log('API will be available at: http://localhost:3008', 'green');
|
||||
console.log('');
|
||||
log('Press Ctrl+C to stop the containers.', 'yellow');
|
||||
|
||||
await new Promise((resolve) => {
|
||||
processes.docker.on('close', resolve);
|
||||
});
|
||||
|
||||
break;
|
||||
} else {
|
||||
log('Invalid choice. Please enter 1 or 2.', 'red');
|
||||
log('Invalid choice. Please enter 1, 2, or 3.', 'red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,6 +496,7 @@ export function printModeMenu() {
|
||||
console.log('═══════════════════════════════════════════════════════');
|
||||
console.log(' 1) Web Application (Browser)');
|
||||
console.log(' 2) Desktop Application (Electron)');
|
||||
console.log(' 3) Docker Container (Isolated)');
|
||||
console.log('═══════════════════════════════════════════════════════');
|
||||
console.log('');
|
||||
}
|
||||
@@ -506,7 +507,7 @@ export function printModeMenu() {
|
||||
|
||||
/**
|
||||
* Create a cleanup handler for spawned processes
|
||||
* @param {object} processes - Object with process references {server, web, electron}
|
||||
* @param {object} processes - Object with process references {server, web, electron, docker}
|
||||
* @returns {Function} - Cleanup function
|
||||
*/
|
||||
export function createCleanupHandler(processes) {
|
||||
@@ -527,6 +528,10 @@ export function createCleanupHandler(processes) {
|
||||
killPromises.push(killProcessTree(processes.electron.pid));
|
||||
}
|
||||
|
||||
if (processes.docker && !processes.docker.killed && processes.docker.pid) {
|
||||
killPromises.push(killProcessTree(processes.docker.pid));
|
||||
}
|
||||
|
||||
await Promise.all(killPromises);
|
||||
};
|
||||
}
|
||||
|
||||
79
start.mjs
79
start.mjs
@@ -18,6 +18,7 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { createRequire } from 'module';
|
||||
import {
|
||||
createRestrictedFs,
|
||||
log,
|
||||
@@ -36,6 +37,9 @@ import {
|
||||
sleep,
|
||||
} from './scripts/launcher-utils.mjs';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const crossSpawn = require('cross-spawn');
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
@@ -47,26 +51,11 @@ const processes = {
|
||||
server: null,
|
||||
web: null,
|
||||
electron: null,
|
||||
docker: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if production builds exist
|
||||
* @returns {{server: boolean, ui: boolean, electron: boolean}}
|
||||
*/
|
||||
function checkBuilds() {
|
||||
const serverDist = path.join(__dirname, 'apps', 'server', 'dist');
|
||||
const uiDist = path.join(__dirname, 'apps', 'ui', 'dist');
|
||||
const electronDist = path.join(__dirname, 'apps', 'ui', 'dist-electron', 'main.js');
|
||||
|
||||
return {
|
||||
server: fs.existsSync(serverDist),
|
||||
ui: fs.existsSync(uiDist),
|
||||
electron: fs.existsSync(electronDist),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all production artifacts if needed
|
||||
* Build all production artifacts
|
||||
*/
|
||||
async function ensureProductionBuilds() {
|
||||
// Always build shared packages first to ensure they're up to date
|
||||
@@ -93,26 +82,16 @@ async function ensureProductionBuilds() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if UI/Electron builds exist (these are slower, so only build if missing)
|
||||
const builds = checkBuilds();
|
||||
|
||||
if (!builds.ui || !builds.electron) {
|
||||
log('UI/Electron builds not found. Building...', 'yellow');
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
// Always rebuild UI to ensure it's in sync with latest code
|
||||
log('Building UI...', 'blue');
|
||||
try {
|
||||
await runNpmAndWait(['run', 'build'], { stdio: 'inherit' }, __dirname);
|
||||
log('✓ Build complete!', 'green');
|
||||
log('✓ UI built', 'green');
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
log(`Build failed: ${error.message}`, 'red');
|
||||
log(`Failed to build UI: ${error.message}`, 'red');
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
log('✓ UI builds found', 'green');
|
||||
console.log('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +121,7 @@ async function main() {
|
||||
|
||||
// Prompt for choice
|
||||
while (true) {
|
||||
const choice = await prompt('Enter your choice (1 or 2): ');
|
||||
const choice = await prompt('Enter your choice (1, 2, or 3): ');
|
||||
|
||||
if (choice === '1') {
|
||||
console.log('');
|
||||
@@ -248,9 +227,43 @@ async function main() {
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
} else if (choice === '3') {
|
||||
console.log('');
|
||||
log('Launching Docker Container (Isolated Mode)...', 'blue');
|
||||
log('Building and starting Docker containers...', 'yellow');
|
||||
console.log('');
|
||||
|
||||
// Check if ANTHROPIC_API_KEY is set
|
||||
if (!process.env.ANTHROPIC_API_KEY) {
|
||||
log('Warning: ANTHROPIC_API_KEY environment variable is not set.', 'yellow');
|
||||
log('The server will require an API key to function.', 'yellow');
|
||||
log('Set it with: export ANTHROPIC_API_KEY=your-key', 'yellow');
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Build and start containers with docker-compose
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up', '--build'], {
|
||||
stdio: 'inherit',
|
||||
cwd: __dirname,
|
||||
env: {
|
||||
...process.env,
|
||||
},
|
||||
});
|
||||
|
||||
log('Docker containers starting...', 'blue');
|
||||
log('UI will be available at: http://localhost:3007', 'green');
|
||||
log('API will be available at: http://localhost:3008', 'green');
|
||||
console.log('');
|
||||
log('Press Ctrl+C to stop the containers.', 'yellow');
|
||||
|
||||
await new Promise((resolve) => {
|
||||
processes.docker.on('close', resolve);
|
||||
});
|
||||
|
||||
break;
|
||||
} else {
|
||||
log('Invalid choice. Please enter 1 or 2.', 'red');
|
||||
log('Invalid choice. Please enter 1, 2, or 3.', 'red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user