Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces stable per-plugin identifiers and uses them to model/validate plugin-to-plugin dependencies driven by dynamic env vars (notably the new shmem type), alongside API typing updates for semaphore mappings.
Changes:
- Add
pluginNamesupport across plugin types, including generation/normalization when creating, importing, editing, or recovering jobs. - Extend dynamic env vars to support variable-length “parts” and a new
shmemtype that references another plugin + env key, plus dependency visualization. - Add dependency tree computation (cycle detection + payload emission) and surface
plugin_semaphore_mapfrom the API into job details.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/typedefs/steps/deploymentStepTypes.ts | Updates dynamic env var value/shape; adds optional pluginName on plugins. |
| src/typedefs/deeploys.ts | Adds pluginSemaphoreMap to running job details. |
| src/typedefs/deeployApi.ts | Extends job_config typing to include plugin_semaphore_map. |
| src/shared/projects/AddJobCard.tsx | Adds JSON import flow and ensures imported plugins get stable pluginNames. |
| src/shared/jobs/DynamicEnvSection.tsx | Refactors dynamic env UI to variable-length parts and adds shmem path selection support. |
| src/schemas/steps/deployment.ts | Adds pluginName to plugin schemas and blocks circular dependencies via superRefine. |
| src/schemas/common.ts | Extends dynamic env schema with path and shmem validation; changes values to variable-length. |
| src/lib/recover-job-from-pipeline.ts | Restores shmem paths using plugin_semaphore_map and hydrates pluginName from configs. |
| src/lib/pluginNames.ts | New helper for stable plugin naming and type detection. |
| src/lib/dependencyTree.ts | New helper to compute dependency edges and detect cycles. |
| src/lib/deeploy-utils.ts | Adds plugin_name to payloads/reserved keys, emits dependency_tree, and handles bigint JSON export. |
| src/lib/contexts/deployment/deployment-provider.tsx | Plumbs plugin_semaphore_map into running job details. |
| src/data/shmemEnvKeys.ts | New list of allowed env keys for shmem references. |
| src/data/dynamicEnvTypes.ts | Adds shmem to supported dynamic env types. |
| src/components/edit-job/JobEditFormWrapper.tsx | Ensures stable plugin names and restores shmem paths from semaphores when editing. |
| src/components/draft/DraftEditFormWrapper.tsx | Ensures stable plugin names when editing drafts. |
| src/components/create-job/plugins/WARInputsSection.tsx | Passes available plugin providers down to dynamic env UI. |
| src/components/create-job/plugins/PluginsSection.tsx | Generates stable plugin names on add, cleans stale shmem refs on remove, computes/displays dependency edges. |
| src/components/create-job/plugins/GenericPluginSections.tsx | Wires available plugin providers into DynamicEnvSection. |
| src/components/create-job/plugins/DependencyTreeView.tsx | New UI component to display dependency edges and cycle warning. |
| src/components/create-job/plugins/CARInputsSection.tsx | Passes available plugin providers down to dynamic env UI. |
| src/components/create-job/JobFormWrapper.tsx | Ensures recovered/merged plugin lists have stable plugin names; seeds initial native plugin name. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {DYNAMIC_ENV_TYPES.map((envType) => ( | ||
| <SelectItem key={envType} textValue={envType}> | ||
| <div className="row gap-2 py-1"> | ||
| <div className="font-medium">{envType}</div> | ||
| </div> | ||
| </SelectItem> | ||
| ))} |
There was a problem hiding this comment.
shmem is always included in the type dropdown, even when availablePlugins is undefined/empty (e.g., the generic job deployment form uses DynamicEnvSection without passing providers). In that case the UI renders a disabled value input and no path selectors, but the schema requires path for shmem, so selecting it makes the form impossible to satisfy until the user manually switches types back. Consider filtering/disable-hiding the shmem option when there are no available provider plugins, or auto-reverting type away from shmem when availablePlugins becomes empty.
| {DYNAMIC_ENV_TYPES.map((envType) => ( | |
| <SelectItem key={envType} textValue={envType}> | |
| <div className="row gap-2 py-1"> | |
| <div className="font-medium">{envType}</div> | |
| </div> | |
| </SelectItem> | |
| ))} | |
| {DYNAMIC_ENV_TYPES.map((envType) => { | |
| const isShmemType = envType === 'shmem'; | |
| const isDisabled = isShmemType && !hasShmemPlugins; | |
| return ( | |
| <SelectItem | |
| key={envType} | |
| textValue={envType} | |
| isDisabled={isDisabled} | |
| > | |
| <div className="row gap-2 py-1"> | |
| <div className="font-medium">{envType}</div> | |
| </div> | |
| </SelectItem> | |
| ); | |
| })} |
Co-authored-by: toderian <vitalii.toderian@gmail.com>
d220b00 to
00aadfe
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .object({ | ||
| key: z.string().optional(), | ||
| values: z.array(dynamicEnvPairSchema).length(3, 'Must have exactly 3 value pairs'), | ||
| values: z.array(dynamicEnvPairSchema).min(1, 'At least one value part is required'), |
There was a problem hiding this comment.
dynamicEnvEntrySchema now allows a variable number of values parts but only enforces .min(1). The UI caps parts at 10 (maxFields={10}), and recovery can now load an arbitrary number of parts. Add a .max(10, ...) (or whatever limit is intended) to the schema so validation matches the UI and prevents oversized payloads.
| values: z.array(dynamicEnvPairSchema).min(1, 'At least one value part is required'), | |
| values: z | |
| .array(dynamicEnvPairSchema) | |
| .min(1, 'At least one value part is required') | |
| .max(10, 'Maximum 10 value parts allowed'), |
| @@ -236,7 +252,8 @@ const normalizeDynamicEnvVars = (config: JobConfig) => { | |||
| }; | |||
| }); | |||
|
|
|||
| while (preparedValues.length < 3) { | |||
| // Ensure at least one part | |||
| if (preparedValues.length === 0) { | |||
| preparedValues.push({ | |||
There was a problem hiding this comment.
normalizeDynamicEnvVars now maps all DYNAMIC_ENV parts without any upper bound. Since the UI caps parts at 10 and the schema currently doesn't enforce a max, a job/pipeline containing a very large array could lead to excessive rendering work and sluggish prefill/edit flows. Consider capping the normalized parts to the same maximum used in the form (and/or ensuring the schema enforces the cap).
| export const formatDynamicEnvVars = ( | ||
| dynamicEnvVars: { key: string; values: { type: string; value: string; path?: [string, string] }[] }[], | ||
| ) => { | ||
| const formatted: Record<string, { type: string; value?: string; path?: [string, string] }[]> = {}; | ||
| dynamicEnvVars.forEach((dynamicEnvVar) => { | ||
| if (dynamicEnvVar.key) { | ||
| formatted[dynamicEnvVar.key] = dynamicEnvVar.values; | ||
| formatted[dynamicEnvVar.key] = dynamicEnvVar.values.map((v) => { | ||
| if (v.type === 'shmem' && v.path) { | ||
| return { type: 'shmem', path: v.path }; | ||
| } | ||
| return { type: v.type, value: v.value }; | ||
| }); |
There was a problem hiding this comment.
formatDynamicEnvVars drops the value field entirely for shmem entries (it returns { type: 'shmem', path }). Other parts of the codebase (and the JobConfig.DYNAMIC_ENV typedef) model dynamic env entries as always having a value key, and recovery logic normalizes shmem to { value: '' }. To avoid backend/consumer breakage and keep the payload shape consistent, include value for shmem as well (e.g., an empty string) and adjust the involved types accordingly.
No description provided.