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,
|
server: null,
|
||||||
web: null,
|
web: null,
|
||||||
electron: null,
|
electron: null,
|
||||||
|
docker: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,7 +97,7 @@ async function main() {
|
|||||||
|
|
||||||
// Prompt for choice
|
// Prompt for choice
|
||||||
while (true) {
|
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') {
|
if (choice === '1') {
|
||||||
console.log('');
|
console.log('');
|
||||||
@@ -167,9 +168,43 @@ async function main() {
|
|||||||
processes.electron.on('close', resolve);
|
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;
|
break;
|
||||||
} else {
|
} 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('═══════════════════════════════════════════════════════');
|
||||||
console.log(' 1) Web Application (Browser)');
|
console.log(' 1) Web Application (Browser)');
|
||||||
console.log(' 2) Desktop Application (Electron)');
|
console.log(' 2) Desktop Application (Electron)');
|
||||||
|
console.log(' 3) Docker Container (Isolated)');
|
||||||
console.log('═══════════════════════════════════════════════════════');
|
console.log('═══════════════════════════════════════════════════════');
|
||||||
console.log('');
|
console.log('');
|
||||||
}
|
}
|
||||||
@@ -506,7 +507,7 @@ export function printModeMenu() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a cleanup handler for spawned processes
|
* 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
|
* @returns {Function} - Cleanup function
|
||||||
*/
|
*/
|
||||||
export function createCleanupHandler(processes) {
|
export function createCleanupHandler(processes) {
|
||||||
@@ -527,6 +528,10 @@ export function createCleanupHandler(processes) {
|
|||||||
killPromises.push(killProcessTree(processes.electron.pid));
|
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);
|
await Promise.all(killPromises);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
87
start.mjs
87
start.mjs
@@ -18,6 +18,7 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
import { createRequire } from 'module';
|
||||||
import {
|
import {
|
||||||
createRestrictedFs,
|
createRestrictedFs,
|
||||||
log,
|
log,
|
||||||
@@ -36,6 +37,9 @@ import {
|
|||||||
sleep,
|
sleep,
|
||||||
} from './scripts/launcher-utils.mjs';
|
} from './scripts/launcher-utils.mjs';
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const crossSpawn = require('cross-spawn');
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
@@ -47,26 +51,11 @@ const processes = {
|
|||||||
server: null,
|
server: null,
|
||||||
web: null,
|
web: null,
|
||||||
electron: null,
|
electron: null,
|
||||||
|
docker: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if production builds exist
|
* Build all production artifacts
|
||||||
* @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
|
|
||||||
*/
|
*/
|
||||||
async function ensureProductionBuilds() {
|
async function ensureProductionBuilds() {
|
||||||
// Always build shared packages first to ensure they're up to date
|
// Always build shared packages first to ensure they're up to date
|
||||||
@@ -93,25 +82,15 @@ async function ensureProductionBuilds() {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if UI/Electron builds exist (these are slower, so only build if missing)
|
// Always rebuild UI to ensure it's in sync with latest code
|
||||||
const builds = checkBuilds();
|
log('Building UI...', 'blue');
|
||||||
|
try {
|
||||||
if (!builds.ui || !builds.electron) {
|
await runNpmAndWait(['run', 'build'], { stdio: 'inherit' }, __dirname);
|
||||||
log('UI/Electron builds not found. Building...', 'yellow');
|
log('✓ UI built', 'green');
|
||||||
console.log('');
|
|
||||||
|
|
||||||
try {
|
|
||||||
log('Building UI...', 'blue');
|
|
||||||
await runNpmAndWait(['run', 'build'], { stdio: 'inherit' }, __dirname);
|
|
||||||
log('✓ Build complete!', 'green');
|
|
||||||
console.log('');
|
|
||||||
} catch (error) {
|
|
||||||
log(`Build failed: ${error.message}`, 'red');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log('✓ UI builds found', 'green');
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
} catch (error) {
|
||||||
|
log(`Failed to build UI: ${error.message}`, 'red');
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +121,7 @@ async function main() {
|
|||||||
|
|
||||||
// Prompt for choice
|
// Prompt for choice
|
||||||
while (true) {
|
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') {
|
if (choice === '1') {
|
||||||
console.log('');
|
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;
|
break;
|
||||||
} else {
|
} 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