feat: version selection for runtimes and databases
Backend: - Add runtimeVersion, phpVersion, dbVersion columns to Application entity - Add version fields to CreateApplicationDto with validation - Node.js Dockerfile: use selected version (22/20/18/16) instead of hardcoded 20 - Laravel Dockerfile: use selected PHP version (8.4/8.3/8.2/8.1) instead of 8.3 - WordPress Dockerfile: use selected WP version (6.7/6.6/6.5/6.4) + PHP version - K8s deployDatabase(): use selected DB version instead of hardcoded postgres:16/mysql:8.0 - K8s restoreDatabaseDump(): match DB image version for restore jobs - Add dbVersion to ManifestContext interface Frontend: - Add runtimeVersion, phpVersion, dbVersion to Application and CreateApplicationDto - Deploy page: Node.js version dropdown (22/20/18/16) - Deploy page: Laravel PHP version dropdown (8.4/8.3/8.2/8.1) - Deploy page: WordPress version + PHP version dropdowns - Deploy page: PostgreSQL version dropdown (17/16/15/14) - Deploy page: MySQL version dropdown (9.0/8.4/8.0/5.7) - Deploy page: auto-set default versions on runtime/DB selection - Review step: show selected versions - App detail page: display runtime + DB versions in config and header
This commit is contained in:
@@ -32,6 +32,21 @@ export class CreateApplicationDto {
|
|||||||
@IsEnum(DatabaseType)
|
@IsEnum(DatabaseType)
|
||||||
databaseType: DatabaseType;
|
databaseType: DatabaseType;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '20', description: 'Runtime version — Node: 20/18/16, WordPress: 6.7/6.6/6.5, Laravel: ignored (uses phpVersion)' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
runtimeVersion?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '8.3', description: 'PHP version for Laravel/WordPress (8.3/8.2/8.1)' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
phpVersion?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '16', description: 'Database version — PostgreSQL: 17/16/15/14, MySQL: 9.0/8.4/8.0' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
dbVersion?: string;
|
||||||
|
|
||||||
@ApiPropertyOptional({ example: 'appuser', description: 'Database username (default: appuser)' })
|
@ApiPropertyOptional({ example: 'appuser', description: 'Database username (default: appuser)' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|||||||
@@ -29,6 +29,15 @@ export class Application {
|
|||||||
@Column({ type: 'enum', enum: DatabaseType, default: DatabaseType.NONE })
|
@Column({ type: 'enum', enum: DatabaseType, default: DatabaseType.NONE })
|
||||||
databaseType: DatabaseType;
|
databaseType: DatabaseType;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
runtimeVersion: string; // e.g. node: '20', '18', '16' | laravel php: '8.3', '8.2' | wordpress: '6.7', '6.6'
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
phpVersion: string; // PHP version for Laravel/WordPress (e.g. '8.3', '8.2', '8.1')
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
dbVersion: string; // e.g. postgres: '17', '16', '15' | mysql: '9.0', '8.4', '8.0'
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
dbUsername: string;
|
dbUsername: string;
|
||||||
|
|
||||||
|
|||||||
@@ -297,8 +297,9 @@ export class BuildService {
|
|||||||
|
|
||||||
private nodeDockerfile(app: Application): string {
|
private nodeDockerfile(app: Application): string {
|
||||||
const port = app.port || 3000;
|
const port = app.port || 3000;
|
||||||
|
const nodeVersion = app.runtimeVersion || '20';
|
||||||
return `# --- Build stage ---
|
return `# --- Build stage ---
|
||||||
FROM node:20-alpine AS builder
|
FROM node:${nodeVersion}-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install --legacy-peer-deps && npm cache clean --force
|
RUN npm install --legacy-peer-deps && npm cache clean --force
|
||||||
@@ -330,7 +331,7 @@ RUN if ([ -f next.config.js ] || [ -f next.config.mjs ] || [ -f next.config.ts ]
|
|||||||
RUN npm run build 2>/dev/null || true
|
RUN npm run build 2>/dev/null || true
|
||||||
|
|
||||||
# --- Production stage ---
|
# --- Production stage ---
|
||||||
FROM node:20-alpine AS runner
|
FROM node:${nodeVersion}-alpine AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
|
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
|
||||||
|
|
||||||
@@ -360,6 +361,7 @@ CMD ["sh", "-c", "if [ \\"$(cat /app/.mode)\\" = \\"standalone\\" ] && [ -f serv
|
|||||||
}
|
}
|
||||||
|
|
||||||
private laravelDockerfile(app: Application): string {
|
private laravelDockerfile(app: Application): string {
|
||||||
|
const phpVersion = app.phpVersion || '8.3';
|
||||||
return `# --- Build stage ---
|
return `# --- Build stage ---
|
||||||
FROM composer:2 AS composer
|
FROM composer:2 AS composer
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -369,7 +371,7 @@ COPY . .
|
|||||||
RUN composer dump-autoload --optimize --no-dev
|
RUN composer dump-autoload --optimize --no-dev
|
||||||
|
|
||||||
# --- Production stage ---
|
# --- Production stage ---
|
||||||
FROM php:8.3-fpm-alpine
|
FROM php:${phpVersion}-fpm-alpine
|
||||||
RUN apk add --no-cache nginx supervisor \\
|
RUN apk add --no-cache nginx supervisor \\
|
||||||
&& docker-php-ext-install pdo pdo_mysql pdo_pgsql opcache
|
&& docker-php-ext-install pdo pdo_mysql pdo_pgsql opcache
|
||||||
|
|
||||||
@@ -387,7 +389,9 @@ CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
|||||||
}
|
}
|
||||||
|
|
||||||
private wordpressDockerfile(app: Application): string {
|
private wordpressDockerfile(app: Application): string {
|
||||||
return `FROM wordpress:6-php8.3-apache
|
const wpVersion = app.runtimeVersion || '6.7';
|
||||||
|
const phpVersion = app.phpVersion || '8.3';
|
||||||
|
return `FROM wordpress:${wpVersion}-php${phpVersion}-apache
|
||||||
|
|
||||||
# Install additional PHP extensions commonly needed by WordPress
|
# Install additional PHP extensions commonly needed by WordPress
|
||||||
RUN docker-php-ext-install opcache
|
RUN docker-php-ext-install opcache
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ interface ManifestContext {
|
|||||||
subdomain: string;
|
subdomain: string;
|
||||||
dbUsername: string;
|
dbUsername: string;
|
||||||
dbPassword: string;
|
dbPassword: string;
|
||||||
|
dbVersion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -97,6 +98,7 @@ export class KubernetesService implements OnModuleInit {
|
|||||||
subdomain: app.subdomain || app.name,
|
subdomain: app.subdomain || app.name,
|
||||||
dbUsername: app.dbUsername || 'appuser',
|
dbUsername: app.dbUsername || 'appuser',
|
||||||
dbPassword: app.dbPassword || this.generatePassword(),
|
dbPassword: app.dbPassword || this.generatePassword(),
|
||||||
|
dbVersion: app.dbVersion || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const manifests: Record<string, any> = {};
|
const manifests: Record<string, any> = {};
|
||||||
@@ -398,7 +400,9 @@ export class KubernetesService implements OnModuleInit {
|
|||||||
|
|
||||||
// Deploy database
|
// Deploy database
|
||||||
const isPostgres = ctx.databaseType === DatabaseType.POSTGRESQL;
|
const isPostgres = ctx.databaseType === DatabaseType.POSTGRESQL;
|
||||||
const image = isPostgres ? 'postgres:16-alpine' : 'mysql:8.0';
|
const defaultDbVersion = isPostgres ? '16' : '8.0';
|
||||||
|
const dbVer = ctx.dbVersion || defaultDbVersion;
|
||||||
|
const image = isPostgres ? `postgres:${dbVer}-alpine` : `mysql:${dbVer}`;
|
||||||
const port = isPostgres ? 5432 : 3306;
|
const port = isPostgres ? 5432 : 3306;
|
||||||
const envVars = isPostgres
|
const envVars = isPostgres
|
||||||
? [
|
? [
|
||||||
@@ -902,7 +906,9 @@ export class KubernetesService implements OnModuleInit {
|
|||||||
`mysql -h ${dbName} -u "$DB_USER" -p"$DB_PASSWORD" ${dbDatabase} < /dump/dump.sql 2>&1`,
|
`mysql -h ${dbName} -u "$DB_USER" -p"$DB_PASSWORD" ${dbDatabase} < /dump/dump.sql 2>&1`,
|
||||||
];
|
];
|
||||||
|
|
||||||
const image = isPostgres ? 'postgres:16-alpine' : 'mysql:8.0';
|
const defaultRestoreDbVer = isPostgres ? '16' : '8.0';
|
||||||
|
const restoreDbVer = app.dbVersion || defaultRestoreDbVer;
|
||||||
|
const image = isPostgres ? `postgres:${restoreDbVer}-alpine` : `mysql:${restoreDbVer}`;
|
||||||
|
|
||||||
// 3. Create the restore Job
|
// 3. Create the restore Job
|
||||||
const job: k8s.V1Job = {
|
const job: k8s.V1Job = {
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ export default function AppDetailPage() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-gray-500 truncate">
|
<p className="text-sm text-gray-500 truncate">
|
||||||
{app.runtime} · {app.subdomain}.apps.cloudhost.local
|
{app.runtime}{app.runtimeVersion ? ` v${app.runtimeVersion}` : ''}{app.phpVersion ? ` — PHP ${app.phpVersion}` : ''} · {app.subdomain}.apps.cloudhost.local
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -419,11 +419,19 @@ export default function AppDetailPage() {
|
|||||||
<dl className="space-y-3">
|
<dl className="space-y-3">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<dt className="text-sm text-gray-500">Runtime</dt>
|
<dt className="text-sm text-gray-500">Runtime</dt>
|
||||||
<dd className="text-sm font-medium text-gray-900">{app.runtime}</dd>
|
<dd className="text-sm font-medium text-gray-900">
|
||||||
|
{app.runtime}
|
||||||
|
{app.runtime === 'nodejs' && app.runtimeVersion ? ` v${app.runtimeVersion}` : ''}
|
||||||
|
{app.runtime === 'wordpress' && app.runtimeVersion ? ` v${app.runtimeVersion}` : ''}
|
||||||
|
{(app.runtime === 'laravel' || app.runtime === 'wordpress') && app.phpVersion ? ` — PHP ${app.phpVersion}` : ''}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<dt className="text-sm text-gray-500">Database</dt>
|
<dt className="text-sm text-gray-500">Database</dt>
|
||||||
<dd className="text-sm font-medium text-gray-900">{app.databaseType}</dd>
|
<dd className="text-sm font-medium text-gray-900">
|
||||||
|
{app.databaseType}
|
||||||
|
{app.databaseType !== 'none' && app.dbVersion ? ` v${app.dbVersion}` : ''}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<dt className="text-sm text-gray-500">Replicas</dt>
|
<dt className="text-sm text-gray-500">Replicas</dt>
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ export default function DeployPage() {
|
|||||||
description: '',
|
description: '',
|
||||||
runtime: 'nodejs',
|
runtime: 'nodejs',
|
||||||
databaseType: 'none',
|
databaseType: 'none',
|
||||||
|
runtimeVersion: '20',
|
||||||
|
phpVersion: '',
|
||||||
|
dbVersion: '',
|
||||||
gitUrl: '',
|
gitUrl: '',
|
||||||
gitToken: '',
|
gitToken: '',
|
||||||
gitBranch: '',
|
gitBranch: '',
|
||||||
@@ -366,17 +369,17 @@ export default function DeployPage() {
|
|||||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||||
{[
|
{[
|
||||||
{ value: 'nodejs', label: 'Node.js', icon: <Hexagon className="w-6 h-6 text-green-500" />, desc: 'Express, NestJS, Fastify...' },
|
{ value: 'nodejs', label: 'Node.js', icon: <Hexagon className="w-6 h-6 text-green-500" />, desc: 'Express, NestJS, Fastify...' },
|
||||||
{ value: 'laravel', label: 'Laravel', icon: <Hexagon className="w-6 h-6 text-orange-500" />, desc: 'PHP 8.3, Composer, Artisan' },
|
{ value: 'laravel', label: 'Laravel', icon: <Hexagon className="w-6 h-6 text-orange-500" />, desc: 'PHP, Composer, Artisan' },
|
||||||
{ value: 'wordpress', label: 'WordPress', icon: <Hexagon className="w-6 h-6 text-blue-600" />, desc: 'PHP 8.3, Apache, wp-content' },
|
{ value: 'wordpress', label: 'WordPress', icon: <Hexagon className="w-6 h-6 text-blue-600" />, desc: 'PHP, Apache, wp-content' },
|
||||||
].map((opt) => (
|
].map((opt) => (
|
||||||
<button
|
<button
|
||||||
key={opt.value}
|
key={opt.value}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const updates: any = { runtime: opt.value as any };
|
const updates: any = { runtime: opt.value as any, phpVersion: '' };
|
||||||
if (opt.value === 'nodejs') updates.port = 3000;
|
if (opt.value === 'nodejs') { updates.port = 3000; updates.runtimeVersion = '20'; }
|
||||||
else if (opt.value === 'laravel') updates.port = 8000;
|
else if (opt.value === 'laravel') { updates.port = 8000; updates.runtimeVersion = ''; updates.phpVersion = '8.3'; }
|
||||||
else if (opt.value === 'wordpress') { updates.port = 80; updates.databaseType = 'mysql'; }
|
else if (opt.value === 'wordpress') { updates.port = 80; updates.databaseType = 'mysql'; updates.runtimeVersion = '6.7'; updates.phpVersion = '8.3'; }
|
||||||
setForm({ ...form, ...updates });
|
setForm({ ...form, ...updates });
|
||||||
}}
|
}}
|
||||||
className={`p-4 rounded-xl border-2 text-left transition-colors ${
|
className={`p-4 rounded-xl border-2 text-left transition-colors ${
|
||||||
@@ -390,6 +393,70 @@ export default function DeployPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Runtime Version Selectors */}
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
{form.runtime === 'nodejs' && (
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">Node.js Version</label>
|
||||||
|
<select
|
||||||
|
className="input-field"
|
||||||
|
value={form.runtimeVersion || '20'}
|
||||||
|
onChange={(e) => setForm({ ...form, runtimeVersion: e.target.value })}
|
||||||
|
>
|
||||||
|
<option value="22">Node.js 22 (LTS)</option>
|
||||||
|
<option value="20">Node.js 20 (LTS)</option>
|
||||||
|
<option value="18">Node.js 18</option>
|
||||||
|
<option value="16">Node.js 16</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{form.runtime === 'laravel' && (
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">PHP Version</label>
|
||||||
|
<select
|
||||||
|
className="input-field"
|
||||||
|
value={form.phpVersion || '8.3'}
|
||||||
|
onChange={(e) => setForm({ ...form, phpVersion: e.target.value })}
|
||||||
|
>
|
||||||
|
<option value="8.4">PHP 8.4</option>
|
||||||
|
<option value="8.3">PHP 8.3 (Recommended)</option>
|
||||||
|
<option value="8.2">PHP 8.2</option>
|
||||||
|
<option value="8.1">PHP 8.1</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{form.runtime === 'wordpress' && (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">WordPress Version</label>
|
||||||
|
<select
|
||||||
|
className="input-field"
|
||||||
|
value={form.runtimeVersion || '6.7'}
|
||||||
|
onChange={(e) => setForm({ ...form, runtimeVersion: e.target.value })}
|
||||||
|
>
|
||||||
|
<option value="6.7">WordPress 6.7 (Latest)</option>
|
||||||
|
<option value="6.6">WordPress 6.6</option>
|
||||||
|
<option value="6.5">WordPress 6.5</option>
|
||||||
|
<option value="6.4">WordPress 6.4</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">PHP Version</label>
|
||||||
|
<select
|
||||||
|
className="input-field"
|
||||||
|
value={form.phpVersion || '8.3'}
|
||||||
|
onChange={(e) => setForm({ ...form, phpVersion: e.target.value })}
|
||||||
|
>
|
||||||
|
<option value="8.3">PHP 8.3 (Recommended)</option>
|
||||||
|
<option value="8.2">PHP 8.2</option>
|
||||||
|
<option value="8.1">PHP 8.1</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||||
Database
|
Database
|
||||||
@@ -410,7 +477,7 @@ export default function DeployPage() {
|
|||||||
key={opt.value}
|
key={opt.value}
|
||||||
type="button"
|
type="button"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={() => setForm({ ...form, databaseType: opt.value as any })}
|
onClick={() => setForm({ ...form, databaseType: opt.value as any, dbVersion: opt.value === 'postgresql' ? '16' : opt.value === 'mysql' ? '8.0' : '' })}
|
||||||
className={`p-4 rounded-xl border-2 text-center transition-colors ${
|
className={`p-4 rounded-xl border-2 text-center transition-colors ${
|
||||||
form.databaseType === opt.value ? 'border-primary-500 bg-primary-50' : 'border-gray-200 hover:border-gray-300'
|
form.databaseType === opt.value ? 'border-primary-500 bg-primary-50' : 'border-gray-200 hover:border-gray-300'
|
||||||
} ${disabled ? 'opacity-40 cursor-not-allowed' : ''}`}
|
} ${disabled ? 'opacity-40 cursor-not-allowed' : ''}`}
|
||||||
@@ -423,6 +490,36 @@ export default function DeployPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Database Version — shown when a DB is selected */}
|
||||||
|
{form.databaseType !== 'none' && (
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
{form.databaseType === 'postgresql' ? 'PostgreSQL' : 'MySQL'} Version
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="input-field max-w-xs"
|
||||||
|
value={form.dbVersion || (form.databaseType === 'postgresql' ? '16' : '8.0')}
|
||||||
|
onChange={(e) => setForm({ ...form, dbVersion: e.target.value })}
|
||||||
|
>
|
||||||
|
{form.databaseType === 'postgresql' ? (
|
||||||
|
<>
|
||||||
|
<option value="17">PostgreSQL 17 (Latest)</option>
|
||||||
|
<option value="16">PostgreSQL 16 (LTS)</option>
|
||||||
|
<option value="15">PostgreSQL 15</option>
|
||||||
|
<option value="14">PostgreSQL 14</option>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<option value="9.0">MySQL 9.0 (Latest)</option>
|
||||||
|
<option value="8.4">MySQL 8.4 (LTS)</option>
|
||||||
|
<option value="8.0">MySQL 8.0</option>
|
||||||
|
<option value="5.7">MySQL 5.7</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Database Credentials — shown when a DB is selected */}
|
{/* Database Credentials — shown when a DB is selected */}
|
||||||
{form.databaseType !== 'none' && (
|
{form.databaseType !== 'none' && (
|
||||||
<div className="p-4 bg-blue-50/50 border border-blue-200 rounded-xl space-y-4">
|
<div className="p-4 bg-blue-50/50 border border-blue-200 rounded-xl space-y-4">
|
||||||
@@ -828,11 +925,19 @@ export default function DeployPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-sm text-gray-500">Runtime</span>
|
<span className="text-sm text-gray-500">Runtime</span>
|
||||||
<span className="text-sm font-medium">{form.runtime}</span>
|
<span className="text-sm font-medium">
|
||||||
|
{form.runtime}
|
||||||
|
{form.runtime === 'nodejs' && form.runtimeVersion ? ` v${form.runtimeVersion}` : ''}
|
||||||
|
{form.runtime === 'wordpress' && form.runtimeVersion ? ` v${form.runtimeVersion}` : ''}
|
||||||
|
{(form.runtime === 'laravel' || form.runtime === 'wordpress') && form.phpVersion ? ` — PHP ${form.phpVersion}` : ''}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-sm text-gray-500">Database</span>
|
<span className="text-sm text-gray-500">Database</span>
|
||||||
<span className="text-sm font-medium">{form.databaseType}</span>
|
<span className="text-sm font-medium">
|
||||||
|
{form.databaseType}
|
||||||
|
{form.databaseType !== 'none' && form.dbVersion ? ` v${form.dbVersion}` : ''}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{form.databaseType !== 'none' && (
|
{form.databaseType !== 'none' && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ export interface Application {
|
|||||||
description?: string;
|
description?: string;
|
||||||
runtime: 'nodejs' | 'laravel' | 'wordpress';
|
runtime: 'nodejs' | 'laravel' | 'wordpress';
|
||||||
databaseType: 'mysql' | 'postgresql' | 'none';
|
databaseType: 'mysql' | 'postgresql' | 'none';
|
||||||
|
runtimeVersion?: string;
|
||||||
|
phpVersion?: string;
|
||||||
|
dbVersion?: string;
|
||||||
dbUsername?: string;
|
dbUsername?: string;
|
||||||
dbPassword?: string;
|
dbPassword?: string;
|
||||||
gitUrl?: string;
|
gitUrl?: string;
|
||||||
@@ -89,6 +92,9 @@ export interface CreateApplicationDto {
|
|||||||
description?: string;
|
description?: string;
|
||||||
runtime: 'nodejs' | 'laravel' | 'wordpress';
|
runtime: 'nodejs' | 'laravel' | 'wordpress';
|
||||||
databaseType: 'mysql' | 'postgresql' | 'none';
|
databaseType: 'mysql' | 'postgresql' | 'none';
|
||||||
|
runtimeVersion?: string;
|
||||||
|
phpVersion?: string;
|
||||||
|
dbVersion?: string;
|
||||||
dbUsername?: string;
|
dbUsername?: string;
|
||||||
dbPassword?: string;
|
dbPassword?: string;
|
||||||
gitUrl?: string;
|
gitUrl?: string;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user