FE: Implement Dynamic Cascading Dropdown UI with Rules-Based Configuration

What does this MR do and why?

This change adds support for dynamic, conditional form inputs in a pipeline creation interface. Previously, all form inputs were static and independent of each other. Now, certain inputs can have "rules" that automatically show, hide, or modify their available options based on the values selected in other "parent" inputs.

For example, if you select "AWS" as your cloud provider and "development" as your environment, the system will automatically show relevant instance types like "t3.micro" and "t3.small". If you change the environment to "production", it will update to show different options like "m5.large" and "m5.xlarge". If you switch to a different cloud provider like "Google Cloud", it will show completely different instance types.

The system intelligently manages these relationships - when parent inputs change, child inputs automatically update their available options, preserve valid existing selections, or reset to defaults when the current value is no longer valid. Inputs with dynamic rules are excluded from the manual selection interface since they're managed automatically.

References

Screenshots or screen recordings

Pipeline schedule page - note that inputs not selected use their default values. In the video, you can see how the child input appears once its rule gets fulfilled with one parent input selected and another using the default value.

Screen_Recording_2025-09-26_at_16.28.38

Pipeline creation page - the inputs are preselected by default.

Screen_Recording_2025-09-26_at_16.29.22

How to set up and validate locally

  1. Enable the ci_dynamic_pipeline_inputs feature flag
  2. Visit Build -> Pipelines -> New pipeline page and verify the inputs are working as expected.
  3. Visit Build -> Pipeline schedules -> New schedule and verify the inputs are working as expected.

Use these configurations for testing:

  1. Dynamic input instance_type adapts its available options using conditional rules:
  • AWS dev environment → offers small instances (t3.micro/small)
  • AWS prod environment → offers larger instances (m5.large/xlarge)
  • GCP (any environment) → offers GCP-specific instances (e2-standard-2/4)
  • Fallback → defaults to "standard" for any unmatched combinations
Click to expand
spec:
  inputs:
    cloud_provider:
      options: ["aws", "gcp", "azure"]
      default: "aws"

    environment:
      options: ["dev", "staging", "prod"]
      default: "dev"

    instance_type:
      rules:
        - if: '$[[ inputs.cloud_provider ]] == "aws" && $[[ inputs.environment ]] == "dev"'
          options: ["t3.micro", "t3.small"]
          default: "t3.micro"
        - if: '$[[ inputs.cloud_provider ]] == "aws" && $[[ inputs.environment ]] == "prod"'
          options: ["m5.large", "m5.xlarge"]
          default: "m5.large"
        - if: '$[[ inputs.cloud_provider ]] == "gcp"'
          options: ["e2-standard-2", "e2-standard-4"]
          default: "e2-standard-2"
        - options: ["standard"]
          default: "standard"

---
provision:
  script: echo "Provisioning $[[ inputs.instance_type ]] on $[[ inputs.cloud_provider ]] 1"
  1. Dynamic input feature_flags adapts its available options based on the selected region:
  • US East 1 → full feature set available (features a, b, c) with no default
  • EU West 1 → limited features (a, d) with "feature_a" as default
  • Other regions (us-west-2) → minimal feature set (only feature_a) with default
Click to expand
spec:
  inputs:
    region:
      options: ["us-east-1", "us-west-2", "eu-west-1"]
      default: "us-east-1"
    feature_flags:
      rules:
        - if: $[[ inputs.region ]] == "us-east-1"
          options: ["feature_a", "feature_b", "feature_c"]
        - if: $[[ inputs.region ]] == "eu-west-1"
          options: ["feature_a", "feature_d"]
          default: "feature_a"
        - options: ["feature_a"]
          default: "feature_a"

---
jobby_job:
  script: echo "$[[ inputs.region ]]"
  1. Dynamic input instance_type uses compound conditions with logical operators:
  • Premium tier (Rule 1): Unlocked by either:

    • AWS production environment (aws AND prod)
    • OR premium flag enabled (regardless of provider/environment)
    • Offers high-end instances (m5.xlarge/2xlarge)
  • GCP standard (Rule 2): Any GCP deployment gets GCP-specific instances

  • Basic tier (Rule 3): Fallback for all other combinations gets minimal instance (t3.micro)

Click to expand

spec: inputs: cloud_provider: options: ["aws", "gcp", "azure"] default: "aws"

environment:
  options: ["dev", "staging", "prod"]
  default: "dev"

enable_premium:
  options: ["true", "false"]
  default: "false"

instance_type:
  rules:
    # Rule 1: (aws AND prod) OR enable_premium
    # This tests: nested AND inside an OR
    - if: '$[[ inputs.cloud_provider ]] == "aws" && $[[ inputs.environment ]] == "prod" || $[[ inputs.enable_premium ]] == "true"'
      options: ["m5.xlarge", "m5.2xlarge"]
      default: "m5.xlarge"
    
    # Rule 2: Simple condition for comparison
    - if: '$[[ inputs.cloud_provider ]] == "gcp"'
      options: ["e2-standard-2", "e2-standard-4"]
      default: "e2-standard-2"
    
    # Rule 3: Fallback
    - options: ["t3.micro"]
      default: "t3.micro"

provision: script: echo "Provisioning $inputs.instance_type on $inputs.cloud_provider"

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #572500

Edited by Anna Vovchenko

Merge request reports

Loading