Skip to content

Commit 2c03d1b

Browse files
authored
Fix pipeline types / inputs / make car and war custom params editable (#37)
* fix: add loopback pipeline type * fix: job edit form signature set up * fix: target nodes inputs count * fix: key value entries field validation * fix: worker app runner public url detection * chore: inc version * fix: make app alias non-editable * fix: validation for plugin custom parameters * fix: custom params editable for car/war plugins
1 parent 054fee2 commit 2c03d1b

File tree

15 files changed

+183
-30
lines changed

15 files changed

+183
-30
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "deeploy-dapp",
33
"private": true,
44
"type": "module",
5-
"version": "0.1.0",
5+
"version": "0.1.1",
66
"scripts": {
77
"dev": "vite",
88
"dev:logs": "vite --debug",

src/components/create-job/JobFormWrapper.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ function JobFormWrapper({ projectName, draftJobsCount }) {
8484
},
8585
restartPolicy: POLICY_TYPES[0],
8686
imagePullPolicy: POLICY_TYPES[0],
87+
customParams: [],
8788
},
8889
});
8990

src/components/create-job/plugins/GenericPluginSections.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ConfigSectionTitle from '@components/job/config/ConfigSectionTitle';
22
import DynamicEnvSection from '@shared/jobs/DynamicEnvSection';
33
import FileVolumesSection from '@shared/jobs/FileVolumesSection';
44
import KeyValueEntriesSection from '@shared/jobs/KeyValueEntriesSection';
5+
import CustomParametersSection from '@shared/jobs/native/CustomParametersSection';
56
import PortMappingSection from '@shared/PortMappingSection';
67
import AppParametersSection from '../sections/AppParametersSection';
78
import PluginEnvVariablesSection from '../sections/PluginEnvVariablesSection';
@@ -34,6 +35,9 @@ export default function GenericPluginSections({ name }: { name: string }) {
3435

3536
<ConfigSectionTitle title="Policies" />
3637
<PoliciesSection baseName={name} />
38+
39+
<ConfigSectionTitle title="Custom Parameters" />
40+
<CustomParametersSection baseName={name} />
3741
</>
3842
);
3943
}

src/components/create-job/steps/deployment/GenericDeployment.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import DynamicEnvSection from '@shared/jobs/DynamicEnvSection';
77
import EnvVariablesCard from '@shared/jobs/EnvVariablesCard';
88
import FileVolumesSection from '@shared/jobs/FileVolumesSection';
99
import KeyValueEntriesSection from '@shared/jobs/KeyValueEntriesSection';
10+
import CustomParametersSection from '@shared/jobs/native/CustomParametersSection';
1011
import TargetNodesCard from '@shared/jobs/target-nodes/TargetNodesCard';
1112
import PortMappingSection from '@shared/PortMappingSection';
1213

@@ -15,7 +16,12 @@ function GenericDeployment({ isEditingRunningJob }: { isEditingRunningJob?: bool
1516
<div className="col gap-6">
1617
<SlateCard title="App Identity">
1718
<div className="flex gap-4">
18-
<InputWithLabel name="deployment.jobAlias" label="Alias" placeholder="My App" />
19+
<InputWithLabel
20+
name="deployment.jobAlias"
21+
label="Alias"
22+
placeholder="My App"
23+
isDisabled={isEditingRunningJob}
24+
/>
1925
</div>
2026
</SlateCard>
2127

@@ -53,6 +59,10 @@ function GenericDeployment({ isEditingRunningJob }: { isEditingRunningJob?: bool
5359
<SlateCard title="Policies">
5460
<PoliciesSection />
5561
</SlateCard>
62+
63+
<SlateCard title="Custom Parameters">
64+
<CustomParametersSection baseName="deployment" />
65+
</SlateCard>
5666
</div>
5767
);
5868
}

src/components/create-job/steps/deployment/NativeDeployment.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ function NativeDeployment({ isEditingRunningJob }: { isEditingRunningJob?: boole
1111
return (
1212
<div className="col gap-6">
1313
<SlateCard title="App Identity">
14-
<InputWithLabel name="deployment.jobAlias" label="Alias" placeholder="My App" />
14+
<InputWithLabel
15+
name="deployment.jobAlias"
16+
label="Alias"
17+
placeholder="My App"
18+
isDisabled={isEditingRunningJob}
19+
/>
1520
</SlateCard>
1621

1722
<TargetNodesCard isEditingRunningJob={isEditingRunningJob} />

src/components/create-job/steps/deployment/ServiceDeployment.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ function ServiceDeployment({ isEditingRunningJob }: { isEditingRunningJob?: bool
7878
<div className="col gap-6">
7979
<SlateCard title="Service Identity">
8080
<div className="flex gap-4">
81-
<InputWithLabel name="deployment.jobAlias" label="Alias" placeholder="Service" />
81+
<InputWithLabel
82+
name="deployment.jobAlias"
83+
label="Alias"
84+
placeholder="Service"
85+
isDisabled={isEditingRunningJob}
86+
/>
8287
</div>
8388
</SlateCard>
8489

src/components/edit-job/JobEditFormWrapper.tsx

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@ import Plugins from '@components/create-job/steps/Plugins';
44
import Services from '@components/create-job/steps/Services';
55
import Specifications from '@components/create-job/steps/Specifications';
66
import { BOOLEAN_TYPES } from '@data/booleanTypes';
7+
import { PLUGIN_SIGNATURE_TYPES } from '@data/pluginSignatureTypes';
78
import { getRunningService } from '@data/containerResources';
89
import { CR_VISIBILITY_OPTIONS } from '@data/crVisibilityOptions';
910
import { zodResolver } from '@hookform/resolvers/zod';
1011
import { DeploymentContextType, useDeploymentContext } from '@lib/contexts/deployment';
11-
import { boolToBooleanType, isGenericPlugin, NATIVE_PLUGIN_DEFAULT_RESPONSE_KEYS, titlecase } from '@lib/deeploy-utils';
12+
import {
13+
boolToBooleanType,
14+
GENERIC_JOB_RESERVED_KEYS,
15+
isGenericPlugin,
16+
NATIVE_PLUGIN_DEFAULT_RESPONSE_KEYS,
17+
titlecase,
18+
} from '@lib/deeploy-utils';
1219
import { Step, STEPS } from '@lib/steps/steps';
1320
import { jobSchema } from '@schemas/index';
1421
import JobFormHeaderInterface from '@shared/jobs/JobFormHeaderInterface';
@@ -111,6 +118,9 @@ export default function JobEditFormWrapper({
111118
// Policies
112119
restartPolicy: titlecase(config.RESTART_POLICY!),
113120
imagePullPolicy: titlecase(config.IMAGE_PULL_POLICY!),
121+
122+
// Custom Parameters
123+
customParams: formatCustomParams(config, GENERIC_JOB_RESERVED_KEYS),
114124
});
115125

116126
const getGenericPluginSchemaDefaults = (config: JobConfig) => ({
@@ -122,18 +132,27 @@ export default function JobEditFormWrapper({
122132
...getGenericSpecificDeploymentDefaults(config),
123133
});
124134

125-
const getNativePluginSchemaDefaults = (pluginInfo: AppsPlugin & { signature: string }) => ({
126-
basePluginType: BasePluginType.Native,
135+
const getNativePluginSchemaDefaults = (pluginInfo: AppsPlugin & { signature: string }) => {
136+
const isKnownSignature = PLUGIN_SIGNATURE_TYPES.includes(
137+
pluginInfo.signature as (typeof PLUGIN_SIGNATURE_TYPES)[number],
138+
);
127139

128-
// Signature
129-
pluginSignature: pluginInfo.signature,
140+
return {
141+
basePluginType: BasePluginType.Native,
130142

131-
// Tunneling
132-
...getBaseSchemaTunnelingDefaults(pluginInfo.instance_conf),
143+
// Signature - if not in the predefined list, select CUSTOM and pre-fill customPluginSignature
144+
pluginSignature: isKnownSignature
145+
? pluginInfo.signature
146+
: PLUGIN_SIGNATURE_TYPES[PLUGIN_SIGNATURE_TYPES.length - 1],
147+
customPluginSignature: isKnownSignature ? undefined : pluginInfo.signature,
133148

134-
// Custom Parameters
135-
customParams: formatCustomParams(pluginInfo.instance_conf),
136-
});
149+
// Tunneling
150+
...getBaseSchemaTunnelingDefaults(pluginInfo.instance_conf),
151+
152+
// Custom Parameters
153+
customParams: formatCustomParams(pluginInfo.instance_conf, NATIVE_PLUGIN_DEFAULT_RESPONSE_KEYS),
154+
};
155+
};
137156

138157
const getBaseSchemaDefaults = (config: JobConfig = jobConfig) => ({
139158
jobType: job.resources.jobType,
@@ -252,11 +271,11 @@ export default function JobEditFormWrapper({
252271
];
253272
};
254273

255-
const formatCustomParams = (config: JobConfig) => {
274+
const formatCustomParams = (config: JobConfig, reservedKeys: (keyof JobConfig)[]) => {
256275
const customParams: CustomParameterEntry[] = [];
257276

258277
Object.entries(config).forEach(([key, value]) => {
259-
if (!NATIVE_PLUGIN_DEFAULT_RESPONSE_KEYS.includes(key as keyof JobConfig)) {
278+
if (!reservedKeys.includes(key as keyof JobConfig)) {
260279
const valueType = typeof value === 'string' ? 'string' : 'json';
261280

262281
let parsedValue: string = '';

src/data/pipelineInputTypes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
export const PIPELINE_INPUT_TYPES = [
2+
'Void',
3+
'Loopback',
24
'JeevesListener',
35
'JeevesApiListener',
46
'JeevesEmbedAgentListener',
57
'JeevesLlmAgentListener',
6-
'void',
78
] as const;

src/lib/deeploy-utils.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
import {
2727
BasePluginType,
2828
ContainerDeploymentType,
29+
CustomParameterEntry,
2930
GenericPlugin,
3031
NativePlugin,
3132
PluginType,
@@ -55,6 +56,41 @@ export const NATIVE_PLUGIN_DEFAULT_RESPONSE_KEYS: (keyof JobConfig)[] = [
5556
'NGROK_USE_API',
5657
];
5758

59+
// Keys that are system-managed and cannot be edited by users
60+
export const SYSTEM_MANAGED_JOB_CONFIG_KEYS: (keyof JobConfig)[] = [
61+
'CHAINSTORE_PEERS',
62+
'CHAINSTORE_RESPONSE_KEY',
63+
'INSTANCE_ID',
64+
'TUNNEL_ENGINE',
65+
'NGROK_AUTH_TOKEN',
66+
'NGROK_EDGE_LABEL',
67+
'NGROK_USE_API',
68+
];
69+
70+
// Keys that are editable via dedicated UI sections in generic job deployment
71+
export const GENERIC_JOB_UI_MANAGED_KEYS: (keyof JobConfig)[] = [
72+
'ENV',
73+
'DYNAMIC_ENV',
74+
'VOLUMES',
75+
'FILE_VOLUMES',
76+
'CONTAINER_RESOURCES',
77+
'PORT',
78+
'TUNNEL_ENGINE_ENABLED',
79+
'CLOUDFLARE_TOKEN',
80+
'RESTART_POLICY',
81+
'IMAGE_PULL_POLICY',
82+
'IMAGE',
83+
'VCS_DATA',
84+
'CR_DATA',
85+
'BUILD_AND_RUN_COMMANDS',
86+
];
87+
88+
// Combined: all keys that should be excluded from custom parameters for generic jobs
89+
export const GENERIC_JOB_RESERVED_KEYS: (keyof JobConfig)[] = [
90+
...SYSTEM_MANAGED_JOB_CONFIG_KEYS,
91+
...GENERIC_JOB_UI_MANAGED_KEYS,
92+
];
93+
5894
export const getDiscountPercentage = (_paymentMonthsCount: number): number => {
5995
// Disabled for now
6096
return 0;
@@ -287,6 +323,20 @@ const formatNativeJobCustomParams = (plugin: NativePlugin) => {
287323
return customParams;
288324
};
289325

326+
const formatGenericJobCustomParams = (customParams: CustomParameterEntry[]) => {
327+
const formatted: Record<string, any> = {};
328+
329+
if (!_.isEmpty(customParams)) {
330+
customParams.forEach((param) => {
331+
if (param.key) {
332+
formatted[param.key] = parseIfJson(param.value);
333+
}
334+
});
335+
}
336+
337+
return formatted;
338+
};
339+
290340
export const formatGenericPluginConfigAndSignature = (
291341
resources: {
292342
cpu: number;
@@ -377,6 +427,8 @@ export const formatGenericJobPayload = (
377427
deployment,
378428
);
379429

430+
const customParams = formatGenericJobCustomParams(deployment.customParams);
431+
380432
const nonce = generateDeeployNonce();
381433

382434
return {
@@ -391,6 +443,7 @@ export const formatGenericJobPayload = (
391443
{
392444
plugin_signature: pluginSignature,
393445
...pluginConfig,
446+
...customParams,
394447
},
395448
],
396449
pipeline_input_type: 'void',
@@ -424,16 +477,20 @@ export const formatNativeJobPayload = (
424477
// Build plugins array
425478
const plugins = deployment.plugins.map((plugin) => {
426479
if (plugin.basePluginType === BasePluginType.Generic) {
427-
const secondaryPluginNodeResources = formatContainerResources(workerType, (plugin as GenericPlugin).ports);
480+
const genericPlugin = plugin as GenericPlugin;
481+
const secondaryPluginNodeResources = formatContainerResources(workerType, genericPlugin.ports);
428482

429483
const { pluginConfig, pluginSignature } = formatGenericPluginConfigAndSignature(
430484
secondaryPluginNodeResources,
431-
plugin as GenericPlugin,
485+
genericPlugin,
432486
);
433487

488+
const customParams = formatGenericJobCustomParams(genericPlugin.customParams);
489+
434490
return {
435491
plugin_signature: pluginSignature,
436492
...pluginConfig,
493+
...customParams,
437494
};
438495
}
439496

src/schemas/steps/deployment.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ const genericAppDeploymentSchemaWihtoutRefinements = baseDeploymentSchema.extend
322322
fileVolumes: validations.fileVolumes,
323323
restartPolicy: validations.restartPolicy,
324324
imagePullPolicy: validations.imagePullPolicy,
325+
customParams: validations.customParams,
325326
});
326327

327328
export const genericAppDeploymentSchema = applyDeploymentTypeRefinements(
@@ -352,6 +353,9 @@ const genericPluginSchema = z.object({
352353
// Policies
353354
restartPolicy: z.enum(POLICY_TYPES, { required_error: 'Value is required' }),
354355
imagePullPolicy: z.enum(POLICY_TYPES, { required_error: 'Value is required' }),
356+
357+
// Custom Parameters
358+
customParams: validations.customParams,
355359
});
356360

357361
const nativePluginSchema = z.object({

0 commit comments

Comments
 (0)