feat: deploy all stacks to shared ai-stack-portal project
- Add SHARED_PROJECT_ID and SHARED_ENVIRONMENT_ID env vars - Add findApplicationByName to Dokploy client for app-based lookup - Update production-deployer to use shared project instead of creating new ones - Update name availability check to query apps in shared environment - Update delete endpoint to remove apps from shared project - Rollback no longer deletes shared project (only app/domain) - Backward compatible: falls back to per-project if env vars not set
This commit is contained in:
110
src/index.ts
110
src/index.ts
@@ -80,7 +80,6 @@ async function deployStack(deploymentId: string): Promise<void> {
|
||||
|
||||
const deployer = new ProductionDeployer(client, progressCallback);
|
||||
|
||||
// Execute deployment with production orchestrator
|
||||
const result = await deployer.deploy({
|
||||
stackName: deployment.stackName,
|
||||
dockerImage: process.env.STACK_IMAGE || 'git.app.flexinit.nl/flexinit/agent-stack:latest',
|
||||
@@ -89,6 +88,8 @@ async function deployStack(deploymentId: string): Promise<void> {
|
||||
healthCheckTimeout: 180000,
|
||||
healthCheckInterval: 5000,
|
||||
registryId: process.env.STACK_REGISTRY_ID,
|
||||
sharedProjectId: process.env.SHARED_PROJECT_ID,
|
||||
sharedEnvironmentId: process.env.SHARED_ENVIRONMENT_ID,
|
||||
});
|
||||
|
||||
// Final update with logs
|
||||
@@ -157,17 +158,29 @@ app.post('/api/deploy', async (c) => {
|
||||
|
||||
const normalizedName = name.trim().toLowerCase();
|
||||
|
||||
// Check if name is already taken
|
||||
const client = createProductionDokployClient();
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
const sharedEnvironmentId = process.env.SHARED_ENVIRONMENT_ID;
|
||||
const appName = `opencode-${normalizedName}`;
|
||||
|
||||
if (existingProject) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Name already taken',
|
||||
code: 'NAME_EXISTS'
|
||||
}, 409);
|
||||
if (sharedEnvironmentId) {
|
||||
const existingApp = await client.findApplicationByName(sharedEnvironmentId, appName);
|
||||
if (existingApp) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Name already taken',
|
||||
code: 'NAME_EXISTS'
|
||||
}, 409);
|
||||
}
|
||||
} else {
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
if (existingProject) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Name already taken',
|
||||
code: 'NAME_EXISTS'
|
||||
}, 409);
|
||||
}
|
||||
}
|
||||
|
||||
// Create deployment state
|
||||
@@ -339,7 +352,6 @@ app.get('/api/check/:name', async (c) => {
|
||||
try {
|
||||
const name = c.req.param('name');
|
||||
|
||||
// Validate name format
|
||||
const validation = validateStackName(name);
|
||||
if (!validation.valid) {
|
||||
return c.json({
|
||||
@@ -350,14 +362,22 @@ app.get('/api/check/:name', async (c) => {
|
||||
}
|
||||
|
||||
const normalizedName = name.trim().toLowerCase();
|
||||
|
||||
// Check if project exists
|
||||
const client = createProductionDokployClient();
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
const sharedEnvironmentId = process.env.SHARED_ENVIRONMENT_ID;
|
||||
|
||||
let exists = false;
|
||||
if (sharedEnvironmentId) {
|
||||
const appName = `opencode-${normalizedName}`;
|
||||
const existingApp = await client.findApplicationByName(sharedEnvironmentId, appName);
|
||||
exists = !!existingApp;
|
||||
} else {
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
exists = !!existingProject;
|
||||
}
|
||||
|
||||
return c.json({
|
||||
available: !existingProject,
|
||||
available: !exists,
|
||||
valid: true,
|
||||
name: normalizedName
|
||||
});
|
||||
@@ -376,29 +396,51 @@ app.delete('/api/stack/:name', async (c) => {
|
||||
try {
|
||||
const name = c.req.param('name');
|
||||
const normalizedName = name.trim().toLowerCase();
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
|
||||
const client = createProductionDokployClient();
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
const sharedEnvironmentId = process.env.SHARED_ENVIRONMENT_ID;
|
||||
|
||||
if (sharedEnvironmentId) {
|
||||
const appName = `opencode-${normalizedName}`;
|
||||
const existingApp = await client.findApplicationByName(sharedEnvironmentId, appName);
|
||||
|
||||
if (!existingApp) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Stack not found',
|
||||
code: 'NOT_FOUND'
|
||||
}, 404);
|
||||
}
|
||||
|
||||
console.log(`Deleting stack: ${appName} (applicationId: ${existingApp.applicationId})`);
|
||||
await client.deleteApplication(existingApp.applicationId);
|
||||
|
||||
if (!existingProject) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Stack not found',
|
||||
code: 'NOT_FOUND'
|
||||
}, 404);
|
||||
success: true,
|
||||
message: `Stack ${normalizedName} deleted successfully`,
|
||||
deletedApplicationId: existingApp.applicationId
|
||||
});
|
||||
} else {
|
||||
const projectName = `ai-stack-${normalizedName}`;
|
||||
const existingProject = await client.findProjectByName(projectName);
|
||||
|
||||
if (!existingProject) {
|
||||
return c.json({
|
||||
success: false,
|
||||
error: 'Stack not found',
|
||||
code: 'NOT_FOUND'
|
||||
}, 404);
|
||||
}
|
||||
|
||||
console.log(`Deleting stack: ${projectName} (projectId: ${existingProject.project.projectId})`);
|
||||
await client.deleteProject(existingProject.project.projectId);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
message: `Stack ${normalizedName} deleted successfully`,
|
||||
deletedProjectId: existingProject.project.projectId
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Deleting stack: ${projectName} (projectId: ${existingProject.project.projectId})`);
|
||||
|
||||
await client.deleteProject(existingProject.project.projectId);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
message: `Stack ${normalizedName} deleted successfully`,
|
||||
deletedProjectId: existingProject.project.projectId
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Delete endpoint error:', error);
|
||||
return c.json({
|
||||
|
||||
Reference in New Issue
Block a user