code: def publish_succeeded_execution(
      metadata_handle: metadata.Metadata,
      execution_id: int,
      contexts: Sequence[metadata_store_pb2.Context],
      output_artifacts: Optional[typing_utils.ArtifactMultiMap] = None,
      executor_output: Optional[
          execution_result_pb2.ExecutorOutput
      ] = None,
  ) -> tuple[
      Optional[typing_utils.ArtifactMultiMap],
      metadata_store_pb2.Execution,
  ]:
      """Marks an existing execution as success.
  
      Also publishes the output artifacts produced by the execution. This method
      will also merge the executor produced info into system generated output
      artifacts. The `last_know_state` of the execution will be changed to
      `COMPLETE` and the output artifacts will be marked as `LIVE`.
  
      Args:
        metadata_handle: A handler to access MLMD.
        execution_id: The id of the execution to mark successful.
        contexts: MLMD contexts to associated with the execution.
        output_artifacts: Output artifacts skeleton of the execution, generated by
          the system. Each artifact will be linked with the execution through an
          event with type OUTPUT.
        executor_output: Executor outputs. `executor_output.output_artifacts` will
          be used to update system-generated output artifacts passed in through
          `output_artifacts` arg. There are three contraints to the update: 1. The
          keys in `executor_output.output_artifacts` are expected to be a subset of
          the system-generated output artifacts dict. 2. An update to a certain key
          should contains all the artifacts under that key. 3. An update to an
          artifact should not change the type of the artifact.
  
      Returns:
        The tuple containing the maybe updated output_artifacts (note that only
        outputs whose key are in executor_output will be updated and others will be
        untouched, that said, it can be partially updated) and the written
        execution.
      Raises:
        RuntimeError: if the executor output to a output channel is partial.
      """
      unpacked_output_artifacts = (
          None  # pylint: disable=g-long-ternary
          if executor_output is None
          else (
              data_types_utils.unpack_executor_output_artifacts(
                  executor_output.output_artifacts
              )
          )
      )
      # TODO(b/300541907) Address corner case if the node returns an ExecutorOutput
      # that contains new or updated artifacts for the intermediate output key,
      # which is not supported.
      merged_output_artifacts = (
          merge_utils.merge_updated_output_artifacts(
              output_artifacts, unpacked_output_artifacts
          )
      )
  
      output_artifacts_to_publish = {}
      for key, artifacts in merged_output_artifacts.items():
          output_artifacts_to_publish[key] = []
          for artifact in artifacts:
              if (
                  artifact.state
                  != types.artifact.ArtifactState.REFERENCE
              ):
                  # Mark output artifact as PUBLISHED (LIVE in MLMD) if it was not in
                  # state REFERENCE.
                  artifact.state = (
                      types.artifact.ArtifactState.PUBLISHED
                  )
  
                  # TODO(b/300541196): Investigate if/how this affects governance.
                  # We don't want to create an OUTPUT_EVENT for the REFERENCE artifact
                  # used for intermediate artifact emission. However, a
                  # PENDING_OUTPUT_EVENT created by the governance task scheduler will
                  # remain in MLMD.
                  output_artifacts_to_publish[key].append(artifact)
  
      [execution] = metadata_handle.store.get_executions_by_id(
          [execution_id]
      )
      execution.last_known_state = metadata_store_pb2.Execution.COMPLETE
      if executor_output:
          for (
              key,
              value,
          ) in executor_output.execution_properties.items():
              execution.custom_properties[key].CopyFrom(value)
      set_execution_result_if_not_empty(executor_output, execution)
  
      execution = execution_lib.put_execution(
          metadata_handle,
          execution,
          contexts,
          output_artifacts=output_artifacts_to_publish,
      )
  
      return output_artifacts_to_publish, execution
  
file_path: tfx/tfx/orchestration/portable/execution_publish_utils.py
imports: from typing import Mapping, Optional, Sequence
  import uuid
  from tfx import types
  from tfx.orchestration import data_types_utils
  from tfx.orchestration import metadata
  from tfx.orchestration.portable import merge_utils
  from tfx.orchestration.portable import outputs_utils
  from tfx.orchestration.portable.mlmd import execution_lib
  from tfx.proto.orchestration import execution_result_pb2
  from tfx.utils import typing_utils
  from ml_metadata.proto import metadata_store_pb2
label_desc: Use image node_id 3 for calling a global function with example usage: publish_succeeded_execution(metadata_handle, execution_id, contexts, output_artifacts, executor_output) and returns: output_artifacts_to_publish,  execution