text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: codepipeline
using AWS.Compat
using AWS.UUIDs

"""
    acknowledge_job(job_id, nonce)
    acknowledge_job(job_id, nonce, params::Dict{String,<:Any})

Returns information about a specified job and whether that job has been received by the job
worker. Used for custom actions only.

# Arguments
- `job_id`: The unique system-generated ID of the job for which you want to confirm receipt.
- `nonce`: A system-generated random number that AWS CodePipeline uses to ensure that the
  job is being worked on by only one job worker. Get this number from the response of the
  PollForJobs request that returned this job.

"""
function acknowledge_job(jobId, nonce; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "AcknowledgeJob",
        Dict{String,Any}("jobId" => jobId, "nonce" => nonce);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function acknowledge_job(
    jobId,
    nonce,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "AcknowledgeJob",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("jobId" => jobId, "nonce" => nonce), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    acknowledge_third_party_job(client_token, job_id, nonce)
    acknowledge_third_party_job(client_token, job_id, nonce, params::Dict{String,<:Any})

Confirms a job worker has received the specified job. Used for partner actions only.

# Arguments
- `client_token`: The clientToken portion of the clientId and clientToken pair used to
  verify that the calling entity is allowed access to the job and its details.
- `job_id`: The unique system-generated ID of the job.
- `nonce`: A system-generated random number that AWS CodePipeline uses to ensure that the
  job is being worked on by only one job worker. Get this number from the response to a
  GetThirdPartyJobDetails request.

"""
function acknowledge_third_party_job(
    clientToken, jobId, nonce; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "AcknowledgeThirdPartyJob",
        Dict{String,Any}("clientToken" => clientToken, "jobId" => jobId, "nonce" => nonce);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function acknowledge_third_party_job(
    clientToken,
    jobId,
    nonce,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "AcknowledgeThirdPartyJob",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "clientToken" => clientToken, "jobId" => jobId, "nonce" => nonce
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_custom_action_type(category, input_artifact_details, output_artifact_details, provider, version)
    create_custom_action_type(category, input_artifact_details, output_artifact_details, provider, version, params::Dict{String,<:Any})

Creates a new custom action that can be used in all pipelines associated with the AWS
account. Only used for custom actions.

# Arguments
- `category`: The category of the custom action, such as a build action or a test action.
- `input_artifact_details`: The details of the input artifact for the action, such as its
  commit ID.
- `output_artifact_details`: The details of the output artifact of the action, such as its
  commit ID.
- `provider`: The provider of the service used in the custom action, such as AWS CodeDeploy.
- `version`: The version identifier of the custom action.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"configurationProperties"`: The configuration properties for the custom action.  You can
  refer to a name in the configuration properties of the custom action within the URL
  templates by following the format of {Config:name}, as long as the configuration property
  is both required and not secret. For more information, see Create a Custom Action for a
  Pipeline.
- `"settings"`: URLs that provide users information about this custom action.
- `"tags"`: The tags for the custom action.
"""
function create_custom_action_type(
    category,
    inputArtifactDetails,
    outputArtifactDetails,
    provider,
    version;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "CreateCustomActionType",
        Dict{String,Any}(
            "category" => category,
            "inputArtifactDetails" => inputArtifactDetails,
            "outputArtifactDetails" => outputArtifactDetails,
            "provider" => provider,
            "version" => version,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_custom_action_type(
    category,
    inputArtifactDetails,
    outputArtifactDetails,
    provider,
    version,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "CreateCustomActionType",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "category" => category,
                    "inputArtifactDetails" => inputArtifactDetails,
                    "outputArtifactDetails" => outputArtifactDetails,
                    "provider" => provider,
                    "version" => version,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_pipeline(pipeline)
    create_pipeline(pipeline, params::Dict{String,<:Any})

Creates a pipeline.  In the pipeline structure, you must include either artifactStore or
artifactStores in your pipeline, but you cannot use both. If you create a cross-region
action in your pipeline, you must use artifactStores.

# Arguments
- `pipeline`: Represents the structure of actions and stages to be performed in the
  pipeline.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: The tags for the pipeline.
"""
function create_pipeline(pipeline; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "CreatePipeline",
        Dict{String,Any}("pipeline" => pipeline);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_pipeline(
    pipeline,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "CreatePipeline",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("pipeline" => pipeline), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_custom_action_type(category, provider, version)
    delete_custom_action_type(category, provider, version, params::Dict{String,<:Any})

Marks a custom action as deleted. PollForJobs for the custom action fails after the action
is marked for deletion. Used for custom actions only.  To re-create a custom action after
it has been deleted you must use a string in the version field that has never been used
before. This string can be an incremented version number, for example. To restore a deleted
custom action, use a JSON file that is identical to the deleted action, including the
original string in the version field.

# Arguments
- `category`: The category of the custom action that you want to delete, such as source or
  deploy.
- `provider`: The provider of the service used in the custom action, such as AWS CodeDeploy.
- `version`: The version of the custom action to delete.

"""
function delete_custom_action_type(
    category, provider, version; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "DeleteCustomActionType",
        Dict{String,Any}(
            "category" => category, "provider" => provider, "version" => version
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_custom_action_type(
    category,
    provider,
    version,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "DeleteCustomActionType",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "category" => category, "provider" => provider, "version" => version
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_pipeline(name)
    delete_pipeline(name, params::Dict{String,<:Any})

Deletes the specified pipeline.

# Arguments
- `name`: The name of the pipeline to be deleted.

"""
function delete_pipeline(name; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "DeletePipeline",
        Dict{String,Any}("name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_pipeline(
    name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "DeletePipeline",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("name" => name), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_webhook(name)
    delete_webhook(name, params::Dict{String,<:Any})

Deletes a previously created webhook by name. Deleting the webhook stops AWS CodePipeline
from starting a pipeline every time an external event occurs. The API returns successfully
when trying to delete a webhook that is already deleted. If a deleted webhook is re-created
by calling PutWebhook with the same name, it will have a different URL.

# Arguments
- `name`: The name of the webhook you want to delete.

"""
function delete_webhook(name; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "DeleteWebhook",
        Dict{String,Any}("name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_webhook(
    name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "DeleteWebhook",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("name" => name), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    deregister_webhook_with_third_party()
    deregister_webhook_with_third_party(params::Dict{String,<:Any})

Removes the connection between the webhook that was created by CodePipeline and the
external tool with events to be detected. Currently supported only for webhooks that target
an action type of GitHub.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"webhookName"`: The name of the webhook you want to deregister.
"""
function deregister_webhook_with_third_party(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "DeregisterWebhookWithThirdParty";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function deregister_webhook_with_third_party(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "DeregisterWebhookWithThirdParty",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    disable_stage_transition(pipeline_name, reason, stage_name, transition_type)
    disable_stage_transition(pipeline_name, reason, stage_name, transition_type, params::Dict{String,<:Any})

Prevents artifacts in a pipeline from transitioning to the next stage in the pipeline.

# Arguments
- `pipeline_name`: The name of the pipeline in which you want to disable the flow of
  artifacts from one stage to another.
- `reason`: The reason given to the user that a stage is disabled, such as waiting for
  manual approval or manual tests. This message is displayed in the pipeline console UI.
- `stage_name`: The name of the stage where you want to disable the inbound or outbound
  transition of artifacts.
- `transition_type`: Specifies whether artifacts are prevented from transitioning into the
  stage and being processed by the actions in that stage (inbound), or prevented from
  transitioning from the stage after they have been processed by the actions in that stage
  (outbound).

"""
function disable_stage_transition(
    pipelineName,
    reason,
    stageName,
    transitionType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "DisableStageTransition",
        Dict{String,Any}(
            "pipelineName" => pipelineName,
            "reason" => reason,
            "stageName" => stageName,
            "transitionType" => transitionType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function disable_stage_transition(
    pipelineName,
    reason,
    stageName,
    transitionType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "DisableStageTransition",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "pipelineName" => pipelineName,
                    "reason" => reason,
                    "stageName" => stageName,
                    "transitionType" => transitionType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    enable_stage_transition(pipeline_name, stage_name, transition_type)
    enable_stage_transition(pipeline_name, stage_name, transition_type, params::Dict{String,<:Any})

Enables artifacts in a pipeline to transition to a stage in a pipeline.

# Arguments
- `pipeline_name`: The name of the pipeline in which you want to enable the flow of
  artifacts from one stage to another.
- `stage_name`: The name of the stage where you want to enable the transition of artifacts,
  either into the stage (inbound) or from that stage to the next stage (outbound).
- `transition_type`: Specifies whether artifacts are allowed to enter the stage and be
  processed by the actions in that stage (inbound) or whether already processed artifacts are
  allowed to transition to the next stage (outbound).

"""
function enable_stage_transition(
    pipelineName,
    stageName,
    transitionType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "EnableStageTransition",
        Dict{String,Any}(
            "pipelineName" => pipelineName,
            "stageName" => stageName,
            "transitionType" => transitionType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function enable_stage_transition(
    pipelineName,
    stageName,
    transitionType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "EnableStageTransition",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "pipelineName" => pipelineName,
                    "stageName" => stageName,
                    "transitionType" => transitionType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_action_type(category, owner, provider, version)
    get_action_type(category, owner, provider, version, params::Dict{String,<:Any})

Returns information about an action type created for an external provider, where the action
is to be used by customers of the external provider. The action can be created with any
supported integration model.

# Arguments
- `category`: Defines what kind of action can be taken in the stage. The following are the
  valid values:    Source     Build     Test     Deploy     Approval     Invoke
- `owner`: The creator of an action type that was created with any supported integration
  model. There are two valid values: AWS and ThirdParty.
- `provider`: The provider of the action type being called. The provider name is specified
  when the action type is created.
- `version`: A string that describes the action type version.

"""
function get_action_type(
    category, owner, provider, version; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetActionType",
        Dict{String,Any}(
            "category" => category,
            "owner" => owner,
            "provider" => provider,
            "version" => version,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_action_type(
    category,
    owner,
    provider,
    version,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "GetActionType",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "category" => category,
                    "owner" => owner,
                    "provider" => provider,
                    "version" => version,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_job_details(job_id)
    get_job_details(job_id, params::Dict{String,<:Any})

Returns information about a job. Used for custom actions only.  When this API is called,
AWS CodePipeline returns temporary credentials for the S3 bucket used to store artifacts
for the pipeline, if the action requires access to that S3 bucket for input or output
artifacts. This API also returns any secret values defined for the action.

# Arguments
- `job_id`: The unique system-generated ID for the job.

"""
function get_job_details(jobId; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "GetJobDetails",
        Dict{String,Any}("jobId" => jobId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_job_details(
    jobId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetJobDetails",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("jobId" => jobId), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_pipeline(name)
    get_pipeline(name, params::Dict{String,<:Any})

Returns the metadata, structure, stages, and actions of a pipeline. Can be used to return
the entire structure of a pipeline in JSON format, which can then be modified and used to
update the pipeline structure with UpdatePipeline.

# Arguments
- `name`: The name of the pipeline for which you want to get information. Pipeline names
  must be unique under an AWS user account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"version"`: The version number of the pipeline. If you do not specify a version,
  defaults to the current version.
"""
function get_pipeline(name; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "GetPipeline",
        Dict{String,Any}("name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_pipeline(
    name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetPipeline",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("name" => name), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_pipeline_execution(pipeline_execution_id, pipeline_name)
    get_pipeline_execution(pipeline_execution_id, pipeline_name, params::Dict{String,<:Any})

Returns information about an execution of a pipeline, including details about artifacts,
the pipeline execution ID, and the name, version, and status of the pipeline.

# Arguments
- `pipeline_execution_id`: The ID of the pipeline execution about which you want to get
  execution details.
- `pipeline_name`: The name of the pipeline about which you want to get execution details.

"""
function get_pipeline_execution(
    pipelineExecutionId, pipelineName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetPipelineExecution",
        Dict{String,Any}(
            "pipelineExecutionId" => pipelineExecutionId, "pipelineName" => pipelineName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_pipeline_execution(
    pipelineExecutionId,
    pipelineName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "GetPipelineExecution",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "pipelineExecutionId" => pipelineExecutionId,
                    "pipelineName" => pipelineName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_pipeline_state(name)
    get_pipeline_state(name, params::Dict{String,<:Any})

Returns information about the state of a pipeline, including the stages and actions.
Values returned in the revisionId and revisionUrl fields indicate the source revision
information, such as the commit ID, for the current state.

# Arguments
- `name`: The name of the pipeline about which you want to get information.

"""
function get_pipeline_state(name; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "GetPipelineState",
        Dict{String,Any}("name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_pipeline_state(
    name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetPipelineState",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("name" => name), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_third_party_job_details(client_token, job_id)
    get_third_party_job_details(client_token, job_id, params::Dict{String,<:Any})

Requests the details of a job for a third party action. Used for partner actions only.
When this API is called, AWS CodePipeline returns temporary credentials for the S3 bucket
used to store artifacts for the pipeline, if the action requires access to that S3 bucket
for input or output artifacts. This API also returns any secret values defined for the
action.

# Arguments
- `client_token`: The clientToken portion of the clientId and clientToken pair used to
  verify that the calling entity is allowed access to the job and its details.
- `job_id`: The unique system-generated ID used for identifying the job.

"""
function get_third_party_job_details(
    clientToken, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "GetThirdPartyJobDetails",
        Dict{String,Any}("clientToken" => clientToken, "jobId" => jobId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_third_party_job_details(
    clientToken,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "GetThirdPartyJobDetails",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("clientToken" => clientToken, "jobId" => jobId),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_action_executions(pipeline_name)
    list_action_executions(pipeline_name, params::Dict{String,<:Any})

Lists the action executions that have occurred in a pipeline.

# Arguments
- `pipeline_name`:  The name of the pipeline for which you want to list action execution
  history.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"filter"`: Input information used to filter action execution history.
- `"maxResults"`: The maximum number of results to return in a single call. To retrieve the
  remaining results, make another call with the returned nextToken value. Action execution
  history is retained for up to 12 months, based on action execution start times. Default
  value is 100.   Detailed execution history is available for executions run on or after
  February 21, 2019.
- `"nextToken"`: The token that was returned from the previous ListActionExecutions call,
  which can be used to return the next set of action executions in the list.
"""
function list_action_executions(
    pipelineName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListActionExecutions",
        Dict{String,Any}("pipelineName" => pipelineName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_action_executions(
    pipelineName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "ListActionExecutions",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("pipelineName" => pipelineName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_action_types()
    list_action_types(params::Dict{String,<:Any})

Gets a summary of all AWS CodePipeline action types associated with your account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"actionOwnerFilter"`: Filters the list of action types to those created by a specified
  entity.
- `"nextToken"`: An identifier that was returned from the previous list action types call,
  which can be used to return the next set of action types in the list.
- `"regionFilter"`: The Region to filter on for the list of action types.
"""
function list_action_types(; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "ListActionTypes"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_action_types(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListActionTypes", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    list_pipeline_executions(pipeline_name)
    list_pipeline_executions(pipeline_name, params::Dict{String,<:Any})

Gets a summary of the most recent executions for a pipeline.

# Arguments
- `pipeline_name`: The name of the pipeline for which you want to get execution summary
  information.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return in a single call. To retrieve the
  remaining results, make another call with the returned nextToken value. Pipeline history is
  limited to the most recent 12 months, based on pipeline execution start times. Default
  value is 100.
- `"nextToken"`: The token that was returned from the previous ListPipelineExecutions call,
  which can be used to return the next set of pipeline executions in the list.
"""
function list_pipeline_executions(
    pipelineName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListPipelineExecutions",
        Dict{String,Any}("pipelineName" => pipelineName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_pipeline_executions(
    pipelineName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "ListPipelineExecutions",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("pipelineName" => pipelineName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_pipelines()
    list_pipelines(params::Dict{String,<:Any})

Gets a summary of all of the pipelines associated with your account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of pipelines to return in a single call. To retrieve
  the remaining pipelines, make another call with the returned nextToken value. The minimum
  value you can specify is 1. The maximum accepted value is 1000.
- `"nextToken"`: An identifier that was returned from the previous list pipelines call. It
  can be used to return the next set of pipelines in the list.
"""
function list_pipelines(; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "ListPipelines"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_pipelines(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListPipelines", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

Gets the set of key-value pairs (metadata) that are used to manage the resource.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource to get tags for.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return in a single call.
- `"nextToken"`: The token that was returned from the previous API call, which would be
  used to return the next page of the list. The ListTagsforResource call lists all available
  tags in one call and does not use pagination.
"""
function list_tags_for_resource(
    resourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListTagsForResource",
        Dict{String,Any}("resourceArn" => resourceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    resourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "ListTagsForResource",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceArn" => resourceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_webhooks()
    list_webhooks(params::Dict{String,<:Any})

Gets a listing of all the webhooks in this AWS Region for this account. The output lists
all webhooks and includes the webhook URL and ARN and the configuration for each webhook.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to return in a single call. To retrieve the
  remaining results, make another call with the returned nextToken value.
- `"NextToken"`: The token that was returned from the previous ListWebhooks call, which can
  be used to return the next set of webhooks in the list.
"""
function list_webhooks(; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "ListWebhooks"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_webhooks(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "ListWebhooks", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    poll_for_jobs(action_type_id)
    poll_for_jobs(action_type_id, params::Dict{String,<:Any})

Returns information about any jobs for AWS CodePipeline to act on. PollForJobs is valid
only for action types with \"Custom\" in the owner field. If the action type contains
\"AWS\" or \"ThirdParty\" in the owner field, the PollForJobs action returns an error.
When this API is called, AWS CodePipeline returns temporary credentials for the S3 bucket
used to store artifacts for the pipeline, if the action requires access to that S3 bucket
for input or output artifacts. This API also returns any secret values defined for the
action.

# Arguments
- `action_type_id`: Represents information about an action type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxBatchSize"`: The maximum number of jobs to return in a poll for jobs call.
- `"queryParam"`: A map of property names and values. For an action type with no queryable
  properties, this value must be null or an empty map. For an action type with a queryable
  property, you must supply that property as a key in the map. Only jobs whose action
  configuration matches the mapped value are returned.
"""
function poll_for_jobs(actionTypeId; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "PollForJobs",
        Dict{String,Any}("actionTypeId" => actionTypeId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function poll_for_jobs(
    actionTypeId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PollForJobs",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("actionTypeId" => actionTypeId), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    poll_for_third_party_jobs(action_type_id)
    poll_for_third_party_jobs(action_type_id, params::Dict{String,<:Any})

Determines whether there are any third party jobs for a job worker to act on. Used for
partner actions only.  When this API is called, AWS CodePipeline returns temporary
credentials for the S3 bucket used to store artifacts for the pipeline, if the action
requires access to that S3 bucket for input or output artifacts.

# Arguments
- `action_type_id`: Represents information about an action type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxBatchSize"`: The maximum number of jobs to return in a poll for jobs call.
"""
function poll_for_third_party_jobs(
    actionTypeId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PollForThirdPartyJobs",
        Dict{String,Any}("actionTypeId" => actionTypeId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function poll_for_third_party_jobs(
    actionTypeId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PollForThirdPartyJobs",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("actionTypeId" => actionTypeId), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_action_revision(action_name, action_revision, pipeline_name, stage_name)
    put_action_revision(action_name, action_revision, pipeline_name, stage_name, params::Dict{String,<:Any})

Provides information to AWS CodePipeline about new revisions to a source.

# Arguments
- `action_name`: The name of the action that processes the revision.
- `action_revision`: Represents information about the version (or revision) of an action.
- `pipeline_name`: The name of the pipeline that starts processing the revision to the
  source.
- `stage_name`: The name of the stage that contains the action that acts on the revision.

"""
function put_action_revision(
    actionName,
    actionRevision,
    pipelineName,
    stageName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutActionRevision",
        Dict{String,Any}(
            "actionName" => actionName,
            "actionRevision" => actionRevision,
            "pipelineName" => pipelineName,
            "stageName" => stageName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_action_revision(
    actionName,
    actionRevision,
    pipelineName,
    stageName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutActionRevision",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "actionName" => actionName,
                    "actionRevision" => actionRevision,
                    "pipelineName" => pipelineName,
                    "stageName" => stageName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_approval_result(action_name, pipeline_name, result, stage_name, token)
    put_approval_result(action_name, pipeline_name, result, stage_name, token, params::Dict{String,<:Any})

Provides the response to a manual approval request to AWS CodePipeline. Valid responses
include Approved and Rejected.

# Arguments
- `action_name`: The name of the action for which approval is requested.
- `pipeline_name`: The name of the pipeline that contains the action.
- `result`: Represents information about the result of the approval request.
- `stage_name`: The name of the stage that contains the action.
- `token`: The system-generated token used to identify a unique approval request. The token
  for each open approval request can be obtained using the GetPipelineState action. It is
  used to validate that the approval request corresponding to this token is still valid.

"""
function put_approval_result(
    actionName,
    pipelineName,
    result,
    stageName,
    token;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutApprovalResult",
        Dict{String,Any}(
            "actionName" => actionName,
            "pipelineName" => pipelineName,
            "result" => result,
            "stageName" => stageName,
            "token" => token,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_approval_result(
    actionName,
    pipelineName,
    result,
    stageName,
    token,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutApprovalResult",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "actionName" => actionName,
                    "pipelineName" => pipelineName,
                    "result" => result,
                    "stageName" => stageName,
                    "token" => token,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_job_failure_result(failure_details, job_id)
    put_job_failure_result(failure_details, job_id, params::Dict{String,<:Any})

Represents the failure of a job as returned to the pipeline by a job worker. Used for
custom actions only.

# Arguments
- `failure_details`: The details about the failure of a job.
- `job_id`: The unique system-generated ID of the job that failed. This is the same ID
  returned from PollForJobs.

"""
function put_job_failure_result(
    failureDetails, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PutJobFailureResult",
        Dict{String,Any}("failureDetails" => failureDetails, "jobId" => jobId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_job_failure_result(
    failureDetails,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutJobFailureResult",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("failureDetails" => failureDetails, "jobId" => jobId),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_job_success_result(job_id)
    put_job_success_result(job_id, params::Dict{String,<:Any})

Represents the success of a job as returned to the pipeline by a job worker. Used for
custom actions only.

# Arguments
- `job_id`: The unique system-generated ID of the job that succeeded. This is the same ID
  returned from PollForJobs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"continuationToken"`: A token generated by a job worker, such as an AWS CodeDeploy
  deployment ID, that a successful job provides to identify a custom action in progress.
  Future jobs use this token to identify the running instance of the action. It can be reused
  to return more information about the progress of the custom action. When the action is
  complete, no continuation token should be supplied.
- `"currentRevision"`: The ID of the current revision of the artifact successfully worked
  on by the job.
- `"executionDetails"`: The execution details of the successful job, such as the actions
  taken by the job worker.
- `"outputVariables"`: Key-value pairs produced as output by a job worker that can be made
  available to a downstream action configuration. outputVariables can be included only when
  there is no continuation token on the request.
"""
function put_job_success_result(jobId; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "PutJobSuccessResult",
        Dict{String,Any}("jobId" => jobId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_job_success_result(
    jobId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PutJobSuccessResult",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("jobId" => jobId), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_third_party_job_failure_result(client_token, failure_details, job_id)
    put_third_party_job_failure_result(client_token, failure_details, job_id, params::Dict{String,<:Any})

Represents the failure of a third party job as returned to the pipeline by a job worker.
Used for partner actions only.

# Arguments
- `client_token`: The clientToken portion of the clientId and clientToken pair used to
  verify that the calling entity is allowed access to the job and its details.
- `failure_details`: Represents information about failure details.
- `job_id`: The ID of the job that failed. This is the same ID returned from
  PollForThirdPartyJobs.

"""
function put_third_party_job_failure_result(
    clientToken, failureDetails, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PutThirdPartyJobFailureResult",
        Dict{String,Any}(
            "clientToken" => clientToken,
            "failureDetails" => failureDetails,
            "jobId" => jobId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_third_party_job_failure_result(
    clientToken,
    failureDetails,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutThirdPartyJobFailureResult",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "clientToken" => clientToken,
                    "failureDetails" => failureDetails,
                    "jobId" => jobId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_third_party_job_success_result(client_token, job_id)
    put_third_party_job_success_result(client_token, job_id, params::Dict{String,<:Any})

Represents the success of a third party job as returned to the pipeline by a job worker.
Used for partner actions only.

# Arguments
- `client_token`: The clientToken portion of the clientId and clientToken pair used to
  verify that the calling entity is allowed access to the job and its details.
- `job_id`: The ID of the job that successfully completed. This is the same ID returned
  from PollForThirdPartyJobs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"continuationToken"`: A token generated by a job worker, such as an AWS CodeDeploy
  deployment ID, that a successful job provides to identify a partner action in progress.
  Future jobs use this token to identify the running instance of the action. It can be reused
  to return more information about the progress of the partner action. When the action is
  complete, no continuation token should be supplied.
- `"currentRevision"`: Represents information about a current revision.
- `"executionDetails"`: The details of the actions taken and results produced on an
  artifact as it passes through stages in the pipeline.
"""
function put_third_party_job_success_result(
    clientToken, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PutThirdPartyJobSuccessResult",
        Dict{String,Any}("clientToken" => clientToken, "jobId" => jobId);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_third_party_job_success_result(
    clientToken,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "PutThirdPartyJobSuccessResult",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("clientToken" => clientToken, "jobId" => jobId),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_webhook(webhook)
    put_webhook(webhook, params::Dict{String,<:Any})

Defines a webhook and returns a unique webhook URL generated by CodePipeline. This URL can
be supplied to third party source hosting providers to call every time there's a code
change. When CodePipeline receives a POST request on this URL, the pipeline defined in the
webhook is started as long as the POST request satisfied the authentication and filtering
requirements supplied when defining the webhook. RegisterWebhookWithThirdParty and
DeregisterWebhookWithThirdParty APIs can be used to automatically configure supported third
parties to call the generated webhook URL.

# Arguments
- `webhook`: The detail provided in an input file to create the webhook, such as the
  webhook name, the pipeline name, and the action name. Give the webhook a unique name that
  helps you identify it. You might name the webhook after the pipeline and action it targets
  so that you can easily recognize what it's used for later.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: The tags for the webhook.
"""
function put_webhook(webhook; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "PutWebhook",
        Dict{String,Any}("webhook" => webhook);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_webhook(
    webhook, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "PutWebhook",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("webhook" => webhook), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    register_webhook_with_third_party()
    register_webhook_with_third_party(params::Dict{String,<:Any})

Configures a connection between the webhook that was created and the external tool with
events to be detected.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"webhookName"`: The name of an existing webhook created with PutWebhook to register with
  a supported third party.
"""
function register_webhook_with_third_party(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "RegisterWebhookWithThirdParty";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function register_webhook_with_third_party(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "RegisterWebhookWithThirdParty",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    retry_stage_execution(pipeline_execution_id, pipeline_name, retry_mode, stage_name)
    retry_stage_execution(pipeline_execution_id, pipeline_name, retry_mode, stage_name, params::Dict{String,<:Any})

Resumes the pipeline execution by retrying the last failed actions in a stage. You can
retry a stage immediately if any of the actions in the stage fail. When you retry, all
actions that are still in progress continue working, and failed actions are triggered again.

# Arguments
- `pipeline_execution_id`: The ID of the pipeline execution in the failed stage to be
  retried. Use the GetPipelineState action to retrieve the current pipelineExecutionId of the
  failed stage
- `pipeline_name`: The name of the pipeline that contains the failed stage.
- `retry_mode`: The scope of the retry attempt. Currently, the only supported value is
  FAILED_ACTIONS.
- `stage_name`: The name of the failed stage to be retried.

"""
function retry_stage_execution(
    pipelineExecutionId,
    pipelineName,
    retryMode,
    stageName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "RetryStageExecution",
        Dict{String,Any}(
            "pipelineExecutionId" => pipelineExecutionId,
            "pipelineName" => pipelineName,
            "retryMode" => retryMode,
            "stageName" => stageName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function retry_stage_execution(
    pipelineExecutionId,
    pipelineName,
    retryMode,
    stageName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "RetryStageExecution",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "pipelineExecutionId" => pipelineExecutionId,
                    "pipelineName" => pipelineName,
                    "retryMode" => retryMode,
                    "stageName" => stageName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_pipeline_execution(name)
    start_pipeline_execution(name, params::Dict{String,<:Any})

Starts the specified pipeline. Specifically, it begins processing the latest commit to the
source location specified as part of the pipeline.

# Arguments
- `name`: The name of the pipeline to start.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"clientRequestToken"`: The system-generated unique ID used to identify a unique
  execution request.
"""
function start_pipeline_execution(name; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "StartPipelineExecution",
        Dict{String,Any}("name" => name, "clientRequestToken" => string(uuid4()));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_pipeline_execution(
    name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "StartPipelineExecution",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("name" => name, "clientRequestToken" => string(uuid4())),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    stop_pipeline_execution(pipeline_execution_id, pipeline_name)
    stop_pipeline_execution(pipeline_execution_id, pipeline_name, params::Dict{String,<:Any})

Stops the specified pipeline execution. You choose to either stop the pipeline execution by
completing in-progress actions without starting subsequent actions, or by abandoning
in-progress actions. While completing or abandoning in-progress actions, the pipeline
execution is in a Stopping state. After all in-progress actions are completed or abandoned,
the pipeline execution is in a Stopped state.

# Arguments
- `pipeline_execution_id`: The ID of the pipeline execution to be stopped in the current
  stage. Use the GetPipelineState action to retrieve the current pipelineExecutionId.
- `pipeline_name`: The name of the pipeline to stop.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"abandon"`: Use this option to stop the pipeline execution by abandoning, rather than
  finishing, in-progress actions.  This option can lead to failed or out-of-sequence tasks.
- `"reason"`: Use this option to enter comments, such as the reason the pipeline was
  stopped.
"""
function stop_pipeline_execution(
    pipelineExecutionId, pipelineName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "StopPipelineExecution",
        Dict{String,Any}(
            "pipelineExecutionId" => pipelineExecutionId, "pipelineName" => pipelineName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function stop_pipeline_execution(
    pipelineExecutionId,
    pipelineName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "StopPipelineExecution",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "pipelineExecutionId" => pipelineExecutionId,
                    "pipelineName" => pipelineName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Adds to or modifies the tags of the given resource. Tags are metadata that can be used to
manage a resource.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource you want to add tags to.
- `tags`: The tags you want to modify or add to the resource.

"""
function tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "TagResource",
        Dict{String,Any}("resourceArn" => resourceArn, "tags" => tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    resourceArn,
    tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "TagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("resourceArn" => resourceArn, "tags" => tags),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Removes tags from an AWS resource.

# Arguments
- `resource_arn`:  The Amazon Resource Name (ARN) of the resource to remove tags from.
- `tag_keys`: The list of keys for the tags to be removed from the resource.

"""
function untag_resource(
    resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return codepipeline(
        "UntagResource",
        Dict{String,Any}("resourceArn" => resourceArn, "tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    resourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "UntagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("resourceArn" => resourceArn, "tagKeys" => tagKeys),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_action_type(action_type)
    update_action_type(action_type, params::Dict{String,<:Any})

Updates an action type that was created with any supported integration model, where the
action type is to be used by customers of the action type provider. Use a JSON file with
the action definition and UpdateActionType to provide the full structure.

# Arguments
- `action_type`: The action type definition for the action type to be updated.

"""
function update_action_type(actionType; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "UpdateActionType",
        Dict{String,Any}("actionType" => actionType);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_action_type(
    actionType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "UpdateActionType",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("actionType" => actionType), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_pipeline(pipeline)
    update_pipeline(pipeline, params::Dict{String,<:Any})

Updates a specified pipeline with edits or changes to its structure. Use a JSON file with
the pipeline structure and UpdatePipeline to provide the full structure of the pipeline.
Updating the pipeline increases the version number of the pipeline by 1.

# Arguments
- `pipeline`: The name of the pipeline to be updated.

"""
function update_pipeline(pipeline; aws_config::AbstractAWSConfig=global_aws_config())
    return codepipeline(
        "UpdatePipeline",
        Dict{String,Any}("pipeline" => pipeline);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_pipeline(
    pipeline,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return codepipeline(
        "UpdatePipeline",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("pipeline" => pipeline), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
#///////////////////////////////////////
#// File Name: forward_backward_simulation.jl
#// Author: Haruki Nishimura (hnishimura@stanford.edu)
#// Date Created: 2021/01/29
#// Description: Forward-backward simulation model for Risk Sensitive SAC
#///////////////////////////////////////

using CUDA
using LinearAlgebra
using PyCall
using Random
using RobotOS
import StatsFuns: logsumexp

# Simulation Parameter
struct SimulationParameter <: Parameter
    dtc::Float64                   # Time Interval for Continuous-time Dynamics
    dto::Float64                   # Time Interval for Discrete-time Dynamics
    prediction_steps::Int64        # Prediction steps for ado robots
    num_samples::Int64             # Number of samples (per ado) for ado simulation
    cost_param::CostParameter
end

function SimulationParameter(traj_scene_loader::TrajectronSceneLoader,
                             traj_predictor::TrajectronPredictor,
                             dtc::Float64, cost_param::CostParameter)
    dto = traj_scene_loader.dto;
    prediction_steps = traj_predictor.param.prediction_steps;
    num_samples = traj_predictor.param.num_samples;
    return SimulationParameter(dtc, dto, prediction_steps, num_samples,
                               cost_param)
end

function SimulationParameter(traj_scene_loader::TrajectronSceneLoader,
                             oracle_predictor::OraclePredictor,
                             dtc::Float64, cost_param::CostParameter)
    dto = traj_scene_loader.dto;
    prediction_steps = oracle_predictor.param.prediction_steps;
    num_samples = 1;
    return SimulationParameter(dtc, dto, prediction_steps, num_samples,
                               cost_param)
end

function SimulationParameter(gaussian_predictor::GaussianPredictor,
                             dtc::Float64, cost_param::CostParameter)
    dto = gaussian_predictor.dto;
    prediction_steps = gaussian_predictor.param.prediction_steps;
    num_samples = gaussian_predictor.param.num_samples;
    return SimulationParameter(dtc, dto, prediction_steps, num_samples,
                               cost_param)
end

# Simulated Cost Result
mutable struct SimulationCostResult
    inst_cnt_cost_array_gpu::CuArray{Float32, 2} # instantaneous control costs: (num_controls, total_timesteps-1)
    inst_pos_cost_array_gpu::CuArray{Float32, 2} # instantaneous position costs: (num_controls, total_timesteps - 1)
    inst_col_cost_array_gpu::CuArray{Float32, 3} # instantaneous collision costs: (num_samples*num_controls, total_timesteps-1, num_ado_agents)

    term_pos_cost_array_gpu::CuArray{Float32, 2} # terminal position costs: (num_controls, 1)
    term_col_cost_array_gpu::CuArray{Float32, 3} # terminal collision costs: (num_samples*num_controls, 1, num_ado_agents)
end

# Simulated Cost Gradient Result
mutable struct SimulationCostGradResult
    inst_pos_cost_grad_array_gpu::CuArray{Float32, 2} # instantaneous position cost gradients: (total_timesteps-1, 4)
    inst_col_cost_grad_array_gpu::CuArray{Float32, 4} # instantaneous collision cost gradients: (num_samples, total_timesteps-1, num_ado_agents, 4)

    term_pos_cost_grad_array_gpu::CuArray{Float32, 2} # terminal position cost gradients: (1, 4) array
    term_col_cost_grad_array_gpu::CuArray{Float32, 4} # terminal collision cost gradients: (num_samples, 1, num_ado_agents, 4)
end

# Simulation Result
mutable struct SimulationResult
    u_nominal_array::Vector{Vector{Float64}} # best nominal control schedule to be used
    u_nominal_idx::Int64 # best nominal control idx
    e_state_array::Vector{RobotState} # simulation of ego robot states
    measurement_schedule::Vector{Time} # measurement schedule
    prediction_dict::Dict{String, Array{Float64, 3}} # predicted ado states (lower time resolution)
    ap_array_gpu::CuArray{Float32, 4} # predicted ado states (higher time resolution, concatenated)
    ado_ids_array::Vector{String} # correspondence between 1st dim of expanded_ap_array and ado agent id
    sampled_total_costs::Vector{Float64} # sampled total costs
    risk_val::Float64 # risk value (i.e. our objective)
    e_costate_array::Array{Float64, 3} # (4, total_timesteps, num_samples) array
    e_costate_array_constraint::Union{Nothing, Array{Float64, 3}} # nothing or (4, constraint_timesteps, num_samples) array
    sampled_total_costs_constraint::Union{Nothing, Vector{Float64}} # nothing or sampled total costs for constraint computation
    risk_constraint::Union{Nothing, Float64} # nothing or risk value for constraint computation
end

# Helper Functions
# # convert array of u_array to 3-dimensional u_array
function process_u_arrays(u_arrays::Vector{Vector{Vector{Float64}}})
    # u_arrays: array of length num_controls of arrays of length total_timesteps-1 of arrays of lenght 2
    num_controls = length(u_arrays)
    total_timesteps = length(u_arrays[1]) + 1
    @assert all([length(u_array) == total_timesteps - 1 for u_array in u_arrays])

    u_array = Array{Float64, 3}(undef, num_controls, total_timesteps - 1, 2)
    for ii = 1:num_controls
        @inbounds u_array[ii, :, :] = permutedims(hcat(u_arrays[ii]...), [2, 1]);
    end
    return u_array
end

# # Forward Simulation
function simulate_forward(e_init::RobotState,
                          u_array::Vector{Vector{Float64}},
                          sim_param::SimulationParameter)
    e_state_array = Vector{RobotState}(undef, length(u_array) + 1);
    e_state_array[1] = e_init;
    for ii in eachindex(u_array)
        @inbounds e_state_array[ii + 1] = transition(e_state_array[ii],
                                                     u_array[ii],
                                                     sim_param.dtc)
    end
    return e_state_array
end
# # Forward Simulation (CUDA version)
function simulate_forward(e_init::RobotState,
                          u_array_gpu::CuArray{Float32, 3}, # multiple nominal control version
                          sim_param::SimulationParameter)
    # ex_init: 4-length vector of initial ego state.
    # u_array_gpu: (num_controls, total_timesteps-1, 2) array of acceleration inputs
    out_vel = similar(u_array_gpu)
    dtc = Float32(sim_param.dtc);
    # compute velocity (Euler integration)
    CUDA.accumulate!(+, out_vel, u_array_gpu.*sim_param.dtc, dims=2);
    out_vel = cat(cu(zeros(size(u_array_gpu, 1), 1, 2)), out_vel, dims=2);
    ev_init = get_velocity(e_init);
    out_vel[:, :, 1] .+= Float32(ev_init[1]);
    out_vel[:, :, 2] .+= Float32(ev_init[2]);

    # compute position (Euler integration)
    out_pos = similar(u_array_gpu)
    CUDA.accumulate!(+, out_pos, out_vel[:, 1:end-1, :].*dtc, dims=2);
    out_pos = cat(cu(zeros(size(u_array_gpu, 1), 1, 2)), out_pos, dims=2);
    ep_init = get_position(e_init);
    out_pos[:, :, 1] .+= Float32(ep_init[1]);
    out_pos[:, :, 2] .+= Float32(ep_init[2]);

    # (num_controls, total_timesteps, 4) array
    return cat(out_pos, out_vel, dims=3)
end

# # Measurement Schedule Handler
function get_measurement_schedule(w_init::WorldState, horizon::Float64,
                                  sim_param::SimulationParameter)
    measurement_schedule =
        Vector{Time}(undef, Int64(round(horizon/sim_param.dto, digits=6)));
    # If no measurement has been taken, assume the initial measurement time of
    # Time(a*dto) where a is the minimum integer so that a*dto > w_init.t
    if w_init.t_last_m == nothing
        a = 0;
        while a*sim_param.dto <= to_sec(w_init.t)
            a += 1;
        end
        measurement_schedule[1] = Time(a*sim_param.dto);
    else
        measurement_schedule[1] =
            w_init.t_last_m + Duration(sim_param.dto);
    end
    for ii = 2:length(measurement_schedule)
        measurement_schedule[ii] =
            measurement_schedule[ii - 1] + Duration(sim_param.dto);
    end
    return measurement_schedule
end
function get_measurement_schedule(w_init::WorldState,
                                  sim_param::SimulationParameter)
    measurement_schedule = Vector{Time}(undef, sim_param.prediction_steps);
    # If no measurement has been taken, assume the initial measurement time of
    # Time(a*dto) where a is the minimum integer so that a*dto > w_init.t
    if w_init.t_last_m == nothing
        a = 0;
        while a*sim_param.dto <= to_sec(w_init.t)
            a += 1;
        end
        measurement_schedule[1] = Time(a*sim_param.dto);
    else
        measurement_schedule[1] =
            w_init.t_last_m + Duration(sim_param.dto);
    end
    for ii = 2:length(measurement_schedule)
        measurement_schedule[ii] =
            measurement_schedule[ii - 1] + Duration(sim_param.dto);
    end
    return measurement_schedule
end

function get_target_pos_array(ex_array_gpu::AbstractArray{Float32, 3},
                              w_init::WorldState,
                              target_trajectory::Trajectory2D,
                              sim_param::SimulationParameter)

    # target_pos_aray_gpu : (total_timesteps, 2)
    # ex_array_gpu : (num_controls, total_timesteps, 4)

    t_array = [w_init.t]
    for ii = 1:size(ex_array_gpu, 2) - 1
        push!(t_array, t_array[end] + Duration(sim_param.dtc))
    end

    target_pos_array = Array(transpose(hcat(map(t -> get_position(target_trajectory, t), t_array)...)));
    return target_pos_array # (total_timesteps, 2) array
end

function process_ap_dict(ex_array_gpu::CuArray{Float32, 3},
                         w_init::WorldState,
                         measurement_schedule::Vector{Time},
                         prediction_dict::Dict{String, Array{Float64, 3}},
                         sim_param::SimulationParameter)

    # prediction_dict : each value is (num_samples*num_controls, prediction_steps, 2) array
    # ap_array : (num_samples*num_controls, prediction_steps + 1, num_ado_agents, 2) array
    # time_idx_ap_array : (total_timesteps) array of time indices for referencing ap_array
    # control_idx_ex_array : (num_samples*num_controls) array of nominal control indices for referencing ex_array
    # ado_ids_array : (num_ado_agents) array of ado ids

    # ratio between dto and dtc
    expansion_factor = Int64(sim_param.dto/sim_param.dtc);
    # number of nominal control candidates
    num_controls = size(ex_array_gpu, 1);

    # total simulation timesteps
    total_timesteps = size(ex_array_gpu, 2);
    # timesteps between current and first measurement time
    init_timesteps =
        Int64(to_nsec(measurement_schedule[1] - w_init.t)/
              (sim_param.dtc*1e9));
    # timesteps between final measurement time and final e_state time
    remaining_timesteps = total_timesteps -
                          (init_timesteps + expansion_factor*(sim_param.prediction_steps - 1));

    # time_idx_ap_array
    time_idx_ap_array = Vector{Int64}(undef, total_timesteps);
    time_idx_ap_array[1:init_timesteps] .= 1;
    time_idx_ap_array[init_timesteps+1:end-remaining_timesteps] = repeat(2:1:sim_param.prediction_steps,
                                                                         inner=expansion_factor);
    time_idx_ap_array[end-remaining_timesteps+1:end] .= sim_param.prediction_steps + 1;

    # control_idx_ex_array
    control_idx_ex_array = repeat(1:1:num_controls, inner=sim_param.num_samples)

    # ado ids
    ado_ids_array = collect(keys(prediction_dict));

    if length(ado_ids_array) == 0
        # if no pedestrian exists, return (num_samples*num_controls, prediction_steps + 1, 0, 2) array
        ap_array = Array{Float64, 4}(undef, sim_param.num_samples*num_controls, sim_param.prediction_steps + 1, 0, 2);
        return ap_array, time_idx_ap_array, control_idx_ex_array, ado_ids_array
    end

    ap_init_array = permutedims(cat([w_init.ap_dict[id] for id in ado_ids_array]..., dims=4),
                                    [2, 3, 4, 1]); # (1, 1, num_ado_agents, 2) array of initial ado positions
    ap_init_array = repeat(ap_init_array, inner=(sim_param.num_samples*num_controls, 1, 1, 1));

    ap_pred_array = permutedims(cat([prediction_dict[id] for id in ado_ids_array]..., dims=4),
                                      [1, 2, 4, 3]); # (num_samples*num_controls, prediction_steps, num_ado_agents, 2) array
    ap_array = cat(ap_init_array, ap_pred_array, dims=2) # (num_samples*num_controls, prediction_steps + 1, num_ado_agents, 2)

    return ap_array, time_idx_ap_array, control_idx_ex_array, ado_ids_array
end

# # Compute costs based on the forward simulation & predicted ado positions
function compute_costs(ex_array_gpu::CuArray{Float32, 3},
                       u_array_gpu::CuArray{Float32, 3},
                       ap_array_gpu::CuArray{Float32, 4},
                       time_idx_ap_array_gpu::CuArray{Int32, 1},
                       control_idx_ex_array_gpu::CuArray{Int32, 1},
                       target_pos_array_gpu::CuArray{Float32, 2},
                       cost_param::CostParameter)
    if name(CuDevice(0)) == "GeForce RTX 2080 Ti"
        # Instataneous costs
        inst_cnt_cost_array_gpu = instant_control_cost(u_array_gpu, cost_param, threads=(16, 64));
        inst_pos_cost_array_gpu = instant_position_cost(ex_array_gpu, target_pos_array_gpu, cost_param, threads=(16, 64));
        inst_col_cost_array_gpu = instant_collision_cost(ex_array_gpu, ap_array_gpu,
                                                         time_idx_ap_array_gpu, control_idx_ex_array_gpu,
                                                         cost_param, threads=(64, 4, 4));
        # Terminal costs
        term_pos_cost_array_gpu = terminal_position_cost(ex_array_gpu, target_pos_array_gpu, cost_param, threads=(1024, 1));
        term_col_cost_array_gpu = terminal_collision_cost(ex_array_gpu, ap_array_gpu,
                                                          time_idx_ap_array_gpu, control_idx_ex_array_gpu,
                                                          cost_param, threads=(128, 1, 8));
    else
        # Instataneous costs
        inst_cnt_cost_array_gpu = instant_control_cost(u_array_gpu, cost_param);
        inst_pos_cost_array_gpu = instant_position_cost(ex_array_gpu, target_pos_array_gpu, cost_param);
        inst_col_cost_array_gpu = instant_collision_cost(ex_array_gpu, ap_array_gpu,
                                                         time_idx_ap_array_gpu, control_idx_ex_array_gpu,
                                                         cost_param);
        # Terminal costs
        term_pos_cost_array_gpu = terminal_position_cost(ex_array_gpu, target_pos_array_gpu, cost_param);
        term_col_cost_array_gpu = terminal_collision_cost(ex_array_gpu, ap_array_gpu,
                                                          time_idx_ap_array_gpu, control_idx_ex_array_gpu,
                                                          cost_param);
    end

    return SimulationCostResult(inst_cnt_cost_array_gpu, inst_pos_cost_array_gpu,
                                inst_col_cost_array_gpu, term_pos_cost_array_gpu,
                                term_col_cost_array_gpu)
end

# # Integrate all the costs over horizon, returning sampled total costs and the risk value
function integrate_costs(cost_result::SimulationCostResult,
                         sim_param::SimulationParameter,
                         constraint_time::Union{Nothing, Float64}=nothing)
    if !isnothing(constraint_time)
        c_idx = Int64(round(constraint_time/sim_param.dtc, digits=5))
        @assert c_idx < size(cost_result.inst_pos_cost_array_gpu, 2);
    else
        c_idx = size(cost_result.inst_cnt_cost_array_gpu, 2);
    end
    # control cost
    cnt_cost_per_control = sum(cost_result.inst_cnt_cost_array_gpu[:, 1:c_idx], dims=2).*Float32(sim_param.dtc);

    # position cost
    pos_cost_per_control = sum(cost_result.inst_pos_cost_array_gpu[:, 1:c_idx], dims=2).*Float32(sim_param.dtc);
    if isnothing(constraint_time)
        pos_cost_per_control += cost_result.term_pos_cost_array_gpu;
    end

    # for collision cost, sum over all timesteps and ado agents but not over samples
    col_cost_per_sample_control = sum(cost_result.inst_col_cost_array_gpu[:, 1:c_idx, :], dims=(2, 3)).*Float32(sim_param.dtc);
    if isnothing(constraint_time)
        col_cost_per_sample_control += sum(cost_result.term_col_cost_array_gpu, dims=3);
    end
    # reshape collision cost into (num_controls, num_samples) array
    col_cost_per_control_sample = permutedims(reshape(col_cost_per_sample_control, sim_param.num_samples, :),
                                              [2, 1]);
    @assert isa(col_cost_per_control_sample, CuArray{Float32, 2});
    num_controls = size(col_cost_per_control_sample, 1);

    # (num_controls, num_samples) array of Float64
    total_cost_per_control_sample = Float64.(collect(col_cost_per_control_sample .+ (cnt_cost_per_control + pos_cost_per_control)));

    # compute risk value per control
    risk_per_control = Vector{Float64}(undef, num_controls);
    for ii = 1:num_controls
        if !(sim_param.cost_param.σ_risk == 0.0)
            risk_value = 1/sim_param.cost_param.σ_risk*
                         logsumexp(sim_param.cost_param.σ_risk.*total_cost_per_control_sample[ii, :] .- log(sim_param.num_samples));
        else
            risk_value = sum(total_cost_per_control_sample[ii, :])./sim_param.num_samples
        end
        @inbounds risk_per_control[ii] = risk_value
    end
    return total_cost_per_control_sample, risk_per_control
end

# Choose best nominal control (i.e. with lowest risk value) for backward simulation
function choose_best_nominal_control(total_cost_per_control_sample, risk_per_control, u_array_gpu)
    minimum_risk, best_control_idx = findmin(risk_per_control);
    sampled_total_costs = total_cost_per_control_sample[best_control_idx, :];

    best_u_array_tmp = Float64.(collect(u_array_gpu[best_control_idx, :, :]));
    best_u_array = [best_u_array_tmp[ii, :] for ii = 1:size(best_u_array_tmp, 1)];

    return sampled_total_costs, minimum_risk, best_control_idx, best_u_array
end

# # Compute cost gradients based on the forward simulation & predicted ado positions
function compute_cost_gradients(best_ex_array_gpu::CuArray{Float32, 2},
                                best_u_array_gpu::CuArray{Float32, 2},
                                best_ap_array_gpu::CuArray{Float32, 4},
                                time_idx_ap_array_gpu::CuArray{Int32, 1},
                                target_pos_array_gpu::CuArray{Float32, 2},
                                cost_param::CostParameter)
    if name(CuDevice(0)) == "GeForce RTX 2080 Ti"
        # Instantaneous costs
        inst_pos_cost_grad_array_gpu = instant_position_cost_gradient(best_ex_array_gpu, target_pos_array_gpu,
                                                                      cost_param, threads=256);
        inst_col_cost_grad_array_gpu = instant_collision_cost_gradient(best_ex_array_gpu, best_ap_array_gpu,
                                                                       time_idx_ap_array_gpu, cost_param,
                                                                       threads=(64, 4, 4));

        # Terminal costs
        term_pos_cost_grad_array_gpu = terminal_position_cost_gradient(best_ex_array_gpu, target_pos_array_gpu,
                                                                       cost_param);
        term_col_cost_grad_array_gpu = terminal_collision_cost_gradient(best_ex_array_gpu, best_ap_array_gpu,
                                                                        time_idx_ap_array_gpu, cost_param, threads=(128, 1, 8));
    else
        # Instantaneous costs
        inst_pos_cost_grad_array_gpu = instant_position_cost_gradient(best_ex_array_gpu, target_pos_array_gpu,
                                                                      cost_param);
        inst_col_cost_grad_array_gpu = instant_collision_cost_gradient(best_ex_array_gpu, best_ap_array_gpu,
                                                                       time_idx_ap_array_gpu, cost_param);

        # Terminal costs
        term_pos_cost_grad_array_gpu = terminal_position_cost_gradient(best_ex_array_gpu, target_pos_array_gpu,
                                                                       cost_param);
        term_col_cost_grad_array_gpu = terminal_collision_cost_gradient(best_ex_array_gpu, best_ap_array_gpu,
                                                                        time_idx_ap_array_gpu, cost_param);
    end
    return SimulationCostGradResult(inst_pos_cost_grad_array_gpu, inst_col_cost_grad_array_gpu,
                                    term_pos_cost_grad_array_gpu, term_col_cost_grad_array_gpu)
end

# # sum cost gradients per timestep and sample, reshaping them to (4, total_timesteps, num_samples) array
function sum_cost_gradients(cost_grad_result::SimulationCostGradResult)
    num_samples = size(cost_grad_result.inst_col_cost_grad_array_gpu, 1);
    total_timesteps = size(cost_grad_result.inst_col_cost_grad_array_gpu, 2) + 1;

    cost_grad_array = Array{Float64, 3}(undef, 4, total_timesteps, num_samples);

    # sum over all ado agents
    inst_col_cost_grads_gpu = sum(cost_grad_result.inst_col_cost_grad_array_gpu, dims=3); # (num_samples, total_timesteps-1, 1, 4)
    term_col_cost_grads_gpu = sum(cost_grad_result.term_col_cost_grad_array_gpu, dims=3); # (num_samples, 1, 1, 4)

    cost_grad_array[:, 1:end-1, :] = collect(dropdims(permutedims(inst_col_cost_grads_gpu, [4, 3, 2, 1]), dims=2)); # (4, total_timesteps-1, num_samples)
    cost_grad_array[:, 1:end-1, :] .+= collect(permutedims(cost_grad_result.inst_pos_cost_grad_array_gpu, [2, 1])); # (4, total_timesteps-1, num_samples)
    cost_grad_array[:, end:end, :] = collect(dropdims(permutedims(term_col_cost_grads_gpu, [4, 3, 2, 1]), dims=2)); # (4, 1, num_samples)
    cost_grad_array[:, end:end, :] .+= collect(permutedims(cost_grad_result.term_pos_cost_grad_array_gpu, [2, 1])); # (4, 1, num_samples)

    return cost_grad_array
end

# # backward simulation of the costates.
function simulate_backward(best_ex_array::Array{Float64, 2}, # (total_timesteps, 4) array
                           best_u_array::Vector{Vector{Float64}},
                           cost_grad_array::Array{Float64, 3},
                           sim_param::SimulationParameter)
    e_costate_array = similar(cost_grad_array); # (4, total_timesteps, num_samples) array
    # boundary conditions
    e_costate_array[:, end, :] = cost_grad_array[:, end, :];

    for jj = Iterators.reverse(1:size(e_costate_array, 2) - 1)
        # backward euler integration
        @inbounds Jacobian =
            transition_jacobian(best_ex_array[jj + 1, :],
                                best_u_array[jj]) # Note the index jj here
        @inbounds costate_vel =
            -cost_grad_array[:, jj, :] .- # Note the index jj here
            transpose(Jacobian)*e_costate_array[:, jj + 1, :];
        @inbounds e_costate_array[:, jj, :] =
            e_costate_array[:, jj + 1, :] .+
            costate_vel*(-sim_param.dtc);
    end
    return e_costate_array
end

# Main Simulation Function (forward-backward simulation)
# Ado positions and predictions must be updated separately.
function simulate(w_init::WorldState,
                  u_arrays::Vector{Vector{Vector{Float64}}},
                  target_trajectory::Trajectory2D,
                  prediction_dict::Dict{String, Array{Float64, 3}},
                  sim_param::SimulationParameter,
                  constraint_time::Union{Nothing, Float64}=nothing)
    # process u_arrays
    u_array = process_u_arrays(u_arrays);
    u_array_gpu = cu(u_array);

    # ego state simulation
    ex_array_gpu = simulate_forward(w_init.e_state, u_array_gpu, sim_param);

    # get measurement schedule
    measurement_schedule = get_measurement_schedule(w_init, sim_param);

    # process prediction_dict for further computation
    # note that each value in prediction_dict has to be (num_samples*num_controls, prediction_steps, 2) array
    ap_array, time_idx_ap_array, control_idx_ex_array, ado_ids_array =
        process_ap_dict(ex_array_gpu, w_init, measurement_schedule, prediction_dict, sim_param);
    ap_array_gpu = cu(ap_array)
    time_idx_ap_array_gpu = CuArray{Int32}(time_idx_ap_array);
    control_idx_ex_array_gpu = CuArray{Int32}(control_idx_ex_array);

    # get target_pos array
    target_pos_array = get_target_pos_array(ex_array_gpu, w_init, target_trajectory, sim_param)
    target_pos_array_gpu = cu(target_pos_array);

    # compute costs
    cost_result = compute_costs(ex_array_gpu, u_array_gpu, ap_array_gpu,
                                time_idx_ap_array_gpu, control_idx_ex_array_gpu,
                                target_pos_array_gpu, sim_param.cost_param);

    # integrate costs
    total_cost_per_control_sample, risk_per_control = integrate_costs(cost_result, sim_param);

    # choose best nominal control
    sampled_total_costs, minimum_risk, best_control_idx, best_u_array =
        choose_best_nominal_control(total_cost_per_control_sample, risk_per_control, u_array_gpu);
    best_ex_array_gpu = ex_array_gpu[best_control_idx, :, :];
    best_ex_array = Float64.(collect(best_ex_array_gpu));
    best_u_array_gpu = u_array_gpu[best_control_idx, :, :];
    best_ap_array_sample_idx =
        sim_param.num_samples*(best_control_idx-1)+1:sim_param.num_samples*best_control_idx
    best_ap_array_gpu = ap_array_gpu[best_ap_array_sample_idx, :, :, :];
    # compute cost gradients using the best nominal control
    cost_grad_result = compute_cost_gradients(best_ex_array_gpu, best_u_array_gpu,
                                              best_ap_array_gpu, time_idx_ap_array_gpu,
                                              target_pos_array_gpu,
                                              sim_param.cost_param);

    # get cost gradient array for costate computation
    cost_grad_array = sum_cost_gradients(cost_grad_result);

    # backward simulation of ego costate
    e_costate_array = simulate_backward(best_ex_array, best_u_array, cost_grad_array, sim_param);

    if !isnothing(constraint_time)
        # compute indices to slice best_ex_array, best_u_array, cost_grad_array for constraint enforcement
        c_idx = Int64(round(constraint_time/sim_param.dtc, digits=5)) + 1;
        @assert c_idx < size(best_ex_array, 1)
        # compute adjoint for constraint enforcement
        cost_grad_array[:, c_idx, :] = zeros(size(cost_grad_array[:, c_idx, :])); # TODO: maybe we do not want to mutate cost_grad_array.
        e_costate_array_constraint = simulate_backward(best_ex_array[1:c_idx, :],
                                                       best_u_array[1:c_idx],
                                                       cost_grad_array[:, 1:c_idx, :],
                                                       sim_param);
        total_cost_per_control_sample_constraint, risk_per_control_constraint =
            integrate_costs(cost_result, sim_param, constraint_time);
        sampled_total_costs_constraint =
            total_cost_per_control_sample_constraint[best_control_idx, :];
        risk_constraint = risk_per_control_constraint[best_control_idx];
    else
        e_costate_array_constraint = nothing;
        sampled_total_costs_constraint = nothing;
        risk_constraint = nothing;
    end

    sim_result = SimulationResult(best_u_array,
                                  best_control_idx,
                                  simulate_forward(w_init.e_state, best_u_array, sim_param),
                                  measurement_schedule, prediction_dict,
                                  best_ap_array_gpu,
                                  ado_ids_array, sampled_total_costs, minimum_risk,
                                  e_costate_array,
                                  e_costate_array_constraint,
                                  sampled_total_costs_constraint,
                                  risk_constraint)
    return sim_result, best_u_array
end

#=
# Forward (re-)simulation and evaluation of risk (for potential line search which is not implemented yet)
function evaluate_risk(w_init::WorldState,
                       u_array::Vector{Vector{Float64}},
                       target_trajectory::Trajectory2D,
                       ap_array_gpu::CuArray{Float32, 4},
                       sim_param::SimulationParameter)
    # ego state simulation
    e_state_array = simulate_forward(w_init.e_state, u_array, sim_param);
    # export to gpu
    ep_array_gpu = cu(hcat(get_position.(e_state_array)...));
    # compute costs
    cost_result = compute_costs(e_state_array, ep_array_gpu, u_array, ap_array_gpu,
                                target_trajectory, sim_param.cost_param);
    ~, risk_val = integrate_costs(cost_result, sim_param);
    return risk_val
end
=#

ext: jl


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule GAP_pkg_io_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("GAP_pkg_io")
JLLWrappers.@generate_main_file("GAP_pkg_io", UUID("19a9678b-966c-568e-9f2e-41ceac70c829"))
end  # module GAP_pkg_io_jll


text:
# Functions for LIIC
module Interpol

using DelimitedFiles
include("converter.jl")
using .Converter

export cartesian, distance, internal, xyz2matrix, writeFile

function cartesian(mol1::Molecule,mol2::Molecule,steps::Int64)
	"""
    This function returns an "steps" length array of Molecule objects
	"""
    # difference = (mol2.Coord - mol1.Coord) / (steps - 1)
    natoms = mol1.Number
	liic = Array{Float64,3}(undef,natoms,3,steps)
    arrayOfMolecules = Array{Molecule, 1}(undef, steps)
    for step in 1:steps
		fracA = (steps-step)/(steps-1)
		fracB = (step-1)/(steps-1)
		liic[:,:,step] = mol1.Coord*fracA + mol2.Coord*fracB
        arrayOfMolecules[step] = Molecule(mol1.Atoms,liic[:,:,step],natoms)
    end
    return arrayOfMolecules
end

function distance()
    println("execute dii")
end

function internal(zmat_f,zmat_l,steps)
	int_f = zmat_f.IntVars
	int_l = zmat_l.IntVars
	natoms = zmat_l.Number
	nvars = length(zmat_l.IntVars)
	difference = Vector(undef,nvars)
	for i in 1:nvars
		toAngle = (zmat_l.IntVars[i]+180.)
		fromAngle = (zmat_f.IntVars[i]+180.)
		diff = abs(toAngle - fromAngle)
		if diff < 180.
			difference[i] = toAngle - fromAngle
		else
			if fromAngle > toAngle
				fromAngle = fromAngle - 360.
				difference[i] = toAngle - fromAngle
			elseif toAngle > fromAngle
				toAngle = toAngle - 360.
				difference[i] = toAngle - fromAngle
			end
		end
	end
	difference = difference / (steps-1)
	liic = Array{Float64,2}(undef,nvars,steps)
	arrayOfZMats = Array{ZMatrix, 1}(undef, steps)
	for step in 1:steps
		liic[:,step] = int_f + (step-1)*difference
		arrayOfZMats[step] = ZMatrix(zmat_f.Atoms,liic[:,step],zmat_f.VarNames,natoms)
	end
	@assert isapprox(int_l,liic[:,steps],atol=1e-5)
	return arrayOfZMats
end

# OLD IMPLEMENTATION THAT USED OPEN BABEL
function internal_babel(int_arr_1,int_arr_2,steps,header)
	"""
	Takes array of Z-matrix internal coordinates and interpolates between them
	to return an array of xyzs.
	"""
	numInternalCrd = size(int_arr_1)[1]
	natoms = Int((numInternalCrd + 6)/3)
	diffVec = Vector(undef,numInternalCrd)
	for i in 1:numInternalCrd
		if ( -180. <= (int_arr_2[i,2]-int_arr_1[i,2]) <= 180. )
			diffVec[i] = (int_arr_2[i,2]-int_arr_1[i,2])/steps
		elseif (int_arr_2[i,2] - int_arr_1[i,2]) < -180.
			diffVec[i] = (int_arr_2[i,2] - int_arr_1[i,2] + 360.)/steps
		elseif (int_arr_2[i,2]-int_arr_1[i,2]) > 180.
			diffVec[i] = (int_arr_2[i,2] - int_arr_1[i,2] - 360.)/steps
		else
			println("Something has gone terribly wrong")
		end
	end
	zmatArray = Vector(undef,steps)
	interXYZ = Array{Float32,3}(undef,natoms,3,steps)
	atom_names = Array{String,1}(undef,natoms)
	for j in 1:steps
		zmatArray[j] = header * "Variables:\n" * intlVec(int_arr_1,diffVec,j)
		open("tmp","w") do io
			write(io,zmatArray[j])
		end
		convXyz = read(`obabel -igzmat tmp -oxyz`,String)
		run(`rm tmp`)
		just_coords = Array{Float32}(readdlm(IOBuffer(convXyz),skipstart=2)[:,2:4])
		atom_names = Array{String}(readdlm(IOBuffer(convXyz),skipstart=2)[:,1])
		interXYZ[:,:,j] = just_coords
	end
	return interXYZ, atom_names
end
# END OF OLD IMPLEMENTATION

function intlVec(int_arr_1,diffVec,step)
	"""
	Function generates set of internal coordinates as a string at a particular
	step during the interpollation to concatenate with a header string to output
	a Z-matrix format string.
	"""
	intlCrd = Vector(undef,length(diffVec))
	for i in 1:length(diffVec)
		intlCrd[i] = string(int_arr_1[i,1]," ",(int_arr_1[i,2]+step*diffVec[i]),"\n")
	end
	return join(intlCrd)
end

function writeFile(output_array,atom_names,file)
    scanLength = size(output_array)[3]
    atom_number = size(output_array)[1]
    open(file,"w") do io
        for i in 1:scanLength
	    geometry = hcat(atom_names,output_array[:,:,i])
            write(io, string(atom_number))
            writedlm(io, "\n")
            writedlm(io, geometry,'\t')
        end
    end
end

function xyz2matrix(input_xyz)
	"""
    Imports .xyz file format as data frame, converts it to an N x 3 Matrix
	"""
    raw_xyz =   readdlm(input_xyz)
    just_coords = Array{Float32}(raw_xyz[2:end,2:4])
    atom_names = Array{String}(raw_xyz[2:end,1])
    return just_coords, atom_names
end

function xyz2internal(input_xyz)
	"""
	Imports .xyz file format to zmat, returns internal coord vector
	"""
    babel_zmat = read(`obabel -ixyz $(input_xyz) -ogzmat`,String)
    regexmatch = match(r"Variables:",babel_zmat)
	coord_segment_zmat = babel_zmat[regexmatch.offset:end]
	header_segment = babel_zmat[1:(regexmatch.offset-1)]
	internals_array = readdlm(IOBuffer(coord_segment_zmat),skipstart=1)
    return internals_array, header_segment
end

end

max_stars_repo_name: dasha-shchep/LIIC

max_issues_repo_name: dasha-shchep/LIIC

max_forks_repo_name: dasha-shchep/LIIC