Repository: kubeflow/pipelines

Issue:
[sdk] Error occurs for component_input_parameter in v2 compiler
### Environment

*  KFP SDK version: 
1.6.3

### Steps to reproduce
Define and execute a pipeline with the following code

```python
slack_notification_op = comp.load_component_from_text(
    read_file("components/slack-notification/component.yaml")
)

def get_before_days(date: str, fmt: str, days: int) -> str:
    """
    Subtract the number of days from the date from the date and the number of days specified in the argument.

    Parameters
    ----------
    date: str
        Original Date
    fmt: str
        Date formate with a (strftime, strptime) format
    days: int
        The number of days to subtract.
    """
    from datetime import datetime, timedelta

    dt = datetime.strptime(date, fmt)
    new_dt = dt - timedelta(days=days)
    return new_dt.strftime(fmt)

@dsl.pipeline(
    name="test",
    description="",
)
def feature_extract_pipeline(
    vertex_pipelines_project_id: str,
    dataset_id: str,
    pipelines_url: str,
    slack_webhook: str,
    target_date: str,
):
    with dsl.ExitHandler(
        exit_op=slack_notification_op(
            job_name="{{workflow.name}}",
            webhook_url=slack_webhook,
            status="{{workflow.status}}",
            pipelines_url=f"{pipelines_url}/pipeline/#/runs/details/{{{{workflow.uid}}}}",
        )
    ):
        get_before_a_days_op = comp.create_component_from_func(
            func=get_before_days, base_image="python:alpine"
        )
        before_a_day = get_before_a_days_op(
            target_date, "%Y%m%d", 1
        )

from kfp.v2 import compiler
import tempfile
with tempfile.TemporaryDirectory() as tempdir:
    package_path = os.path.join(tempdir, "pipeline.json")
    # NOTE: The type_check argument is probably not working.
    compiler.Compiler().compile(pipeline_func=feature_extract_pipeline, package_path=package_path)

```

following is error messsage
```
ata/.pyenv/versions/3.7.1rc1/lib/python3.7/site-packages/kfp/v2/compiler/compiler.py", line 687, in _group_to_dag_spec
    input_artifacts_in_current_dag,
  File "/Users/takuya.hirata/.pyenv/versions/3.7.1rc1/lib/python3.7/site-packages/kfp/dsl/component_spec.py", line 338, in update_task_inputs_spec
    component_input_parameter, parent_component_inputs)
AssertionError: component_input_parameter: pipelineparam--pipelineparam--target_date not found. All inputs:
```


I got same error occurred when using `from kfp.v2.dsl import component`.
~If you use a python function with component, you will get an error like the one above~


### Expected result
No errors occur during compilation.

---

<!-- Don't delete message below to encourage users to support your issue! -->
Impacted by this bug? Give it a 👍. We prioritise the issues with the most 👍.



Discussion:
I noticed that I can compile without using the exit handler.
I just did a print debugging.
The target_date is recognized as a input_parameter of the subgroup component, but there is no such parameter in the parent, which may be causing the above error.

```
**********************group.name***************
group.name: exit-handler-1, rootgroup_name: 8a1b7dd5281c40c3aee5c15a24814903
********************root spec******************
input_definitions {
  parameters {
    key: "category_models"
    value {
      type: STRING
    }
  }
  parameters {
    key: "dataset_id"
    value {
      type: STRING
    }
  }
  parameters {
    key: "metric_bucket_url"
    value {
      type: STRING
    }
  }
  parameters {
    key: "metric_image"
    value {
      type: STRING
    }
  }
  parameters {
    key: "output_gcs_path"
    value {
      type: STRING
    }
  }
  parameters {
    key: "parallel_num"
    value {
      type: INT
    }
  }
  parameters {
    key: "pipelines_url"
    value {
      type: STRING
    }
  }
  parameters {
    key: "service_project_id"
    value {
      type: STRING
    }
  }
  parameters {
    key: "slack_webhook"
    value {
      type: STRING
    }
  }
  parameters {
    key: "snap_item_limit"
    value {
      type: STRING
    }
  }
  parameters {
    key: "target_date"
    value {
      type: STRING
    }
  }
  parameters {
    key: "vertex_pipelines_project_id"
    value {
      type: STRING
    }
  }
}
dag {
  tasks {
    key: "exit-handler-1"
    value {
      task_info {
        name: "exit-handler-1"
      }
      component_ref {
        name: "comp-exit-handler-1"
      }
    }
  }
}

********************group component spec******************
{'comp-exit-handler-1': }

********************subgroup params*****************
[{{pipelineparam:op=;name=target_date}}]
```
https://github.com/kubeflow/pipelines/blob/a41a72f61461569e60107a1c85bfde7ffe05ca88/sdk/python/kfp/v2/compiler/compiler.py#L615-L618
https://github.com/kubeflow/pipelines/blob/a41a72f61461569e60107a1c85bfde7ffe05ca88/sdk/python/kfp/v2/compiler/compiler.py#L663

`exit-handler` group does not have parameters, So I figured the error would occur.


Resolving patch:
diff --git a/sdk/python/kfp/v2/compiler/compiler.py b/sdk/python/kfp/v2/compiler/compiler.py
--- a/sdk/python/kfp/v2/compiler/compiler.py
+++ b/sdk/python/kfp/v2/compiler/compiler.py
@@ -790,6 +790,21 @@ def _group_to_dag_spec(
             pipeline_spec_pb2.PipelineTaskSpec.TriggerPolicy(
                 condition=condition_string))
 
+      if isinstance(subgroup, dsl.OpsGroup) and subgroup.type == 'exit_handler':
+
+        # "punch the hole", adding inputs needed by its subgroup or tasks.
+        dsl_component_spec.build_component_inputs_spec(
+            component_spec=subgroup_component_spec,
+            pipeline_params=subgroup_params,
+            is_root_component=False,
+        )
+        dsl_component_spec.build_task_inputs_spec(
+            subgroup_task_spec,
+            subgroup_params,
+            tasks_in_current_dag,
+            is_parent_component_root,
+        )
+
       # Generate dependencies section for this task.
       if dependencies.get(subgroup.name, None):
         group_dependencies = list(dependencies[subgroup.name])


Test patch:
diff --git a/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.json b/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.json
--- a/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.json
+++ b/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.json
@@ -30,11 +30,7 @@
               "inputs": {
                 "parameters": {
                   "message": {
-                    "runtimeValue": {
-                      "constantValue": {
-                        "stringValue": "Hello World!"
-                      }
-                    }
+                    "componentInputParameter": "pipelineparam--message"
                   }
                 }
               },
@@ -43,6 +39,13 @@
               }
             }
           }
+        },
+        "inputDefinitions": {
+          "parameters": {
+            "pipelineparam--message": {
+              "type": "STRING"
+            }
+          }
         }
       },
       "comp-fail-op": {
@@ -147,6 +150,13 @@
             "componentRef": {
               "name": "comp-exit-handler-1"
             },
+            "inputs": {
+              "parameters": {
+                "pipelineparam--message": {
+                  "componentInputParameter": "message"
+                }
+              }
+            },
             "taskInfo": {
               "name": "exit-handler-1"
             }
@@ -177,12 +187,24 @@
             }
           }
         }
+      },
+      "inputDefinitions": {
+        "parameters": {
+          "message": {
+            "type": "STRING"
+          }
+        }
       }
     },
     "schemaVersion": "2.0.0",
-    "sdkVersion": "kfp-1.6.2"
+    "sdkVersion": "kfp-1.6.3"
   },
   "runtimeConfig": {
-    "gcsOutputDirectory": "dummy_root"
+    "gcsOutputDirectory": "dummy_root",
+    "parameters": {
+      "message": {
+        "stringValue": "Hello World!"
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.py b/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.py
--- a/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.py
+++ b/sdk/python/kfp/v2/compiler_cli_tests/test_data/pipeline_with_exit_handler.py
@@ -33,12 +33,12 @@ def fail_op(message: str):
 
 
 @dsl.pipeline(name='pipeline-with-exit-handler', pipeline_root='dummy_root')
-def my_pipeline():
+def my_pipeline(message: str = 'Hello World!'):
 
   exit_task = print_op('Exit handler has worked!')
 
   with dsl.ExitHandler(exit_task):
-    print_op('Hello World!')
+    print_op(message)
     fail_op('Task failed.')