Skip to content

Instantly share code, notes, and snippets.

@anniethiessen
Last active October 26, 2023 00:39
Show Gist options
  • Select an option

  • Save anniethiessen/f73a3c65e9810b5ee9161e603c5c7be9 to your computer and use it in GitHub Desktop.

Select an option

Save anniethiessen/f73a3c65e9810b5ee9161e603c5c7be9 to your computer and use it in GitHub Desktop.
Script file to package and deploy AWS CloudFormation stacks.
#!/usr/bin/env bash
: '
Script file to package and deploy AWS CloudFormation stacks.
Ensure AWS CLI is installed and configured, ensure STOML is installed,
define script variables and configuration file, then execute script.
Accepts -v (verbose output) and -q (quiet output) arguments.
Prerequisites:
- aws-cli 1.29.62 -> https://pypi.org/project/awscli/
- stoml 0.7.1 -> https://github.com/freshautomations/stoml
- Install Go~=1.16 -> https://go.dev
- Install stoml -> % go install github.com/freshautomations/[email protected]
- Define stoml path script variable, if not ~/go/bin/stoml
Configuration File:
The configuration file replaces aws-cli command options with pre-defined env-specific parameters.
Configuration file format should be in TOML or INI format.
Section headers should be in format [<env>.<command>.parameters].
Global sections are retrieved as a last resort.
Parameters are specified as key-value pairs, with the key
being the aws-cli command option name -- replacing hyphens with underscores (e.g. --template-file -> template_file).
See aws-cli CloudFormation docs for valid command parameters (command options).
Only "true" boolean parameters are supported (e.g. disable_rollback = false will be ignored so use no_disable_rollback = true)
Some parameters may cause conflicts:
- no_execute_change_set: already set by script if ""CONFIRM_CHANGE_SET"" is set to "true"
- change_set_name: should only be set if ""PERFORM_DEPLOY"" is set to "false",
and ""PERFORM_DESCRIBE_CHANGE_SET"" and/or ""PERFORM_EXECUTE_CHANGE_SET"" is set to "true".
This is because the ""deploy"" function creates a new change-set and passes
the change-set name to the ""describe change-set"" and ""execute change-set"" functions.
- no_paginate/max_items/starting_token: pagination is not supported by this script
Script Variables:
- CONDA_ENV: The conda environement that has required packages installed.
Optional, if current environment has them installed.
- STOML_PATH: Path to ""stoml"" go package. Do not surround with quotes.
Optional, defaults to ~/go/bin/stoml.
- CONFIG_FILE: Path and name of AWS CloudFormation configuration file.
Optional, defaults to "config.toml".
- CONFIG_ENV: Environment to use in the AWS configuration file.
Optional, defaults to "default".
- ARCHIVE_S3_BUCKET: S3 bucket to which archive files will be uploaded.
The ""check"" function checks if it exists and provides an option to create it if necessary.
Required, no default.
- ARCHIVE_S3_BUCKET_REGION: AWS region of ""ARCHIVE_S3_BUCKET"", if created.
Optional, defaults to "us-west-2".
- ARCHIVE_S3_BUCKET_TAGS: List of tags to add to ""ARCHIVE_S3_BUCKET"", if created.
Optional, defaults to ().
- PERFORM_CHECK: Whether to perform the ""check"" step.
The ""check"" function checks if required pre-existing resources exist.
Currently, only ""ARCHIVE_S3_BUCKET"".
Optional, defaults to "true".
- PERFORM_PACKAGE: Whether to perform the ""package"" step.
The ""package"" function packages local artifacts that the AWS CloudFormation template references
to S3 and creates a clean output copy of the template, to be used by the ""deploy"" step.
Parameter values for "package" function should be defined in the ""PACKAGE_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"".
Should only be set to "false" if ""PERFORM_DEPLOY"" is also set to "false"
or if a clean template for ""deploy"" step already exists.
Optional, defaults to "true".
- PERFORM_DEPLOY: Whether to perform the ""deploy"" step.
The ""deploy"" function deploys specified template by creating, then executing a change-set.
Parameter values for "package" function should be defined in the ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"".
If ""CONFIRM_CHANGE_SET"" is set to "true", the change-set is displayed first, with an option to cancel deployment.
Optional, defaults to "true".
- CONFIRM_CHANGE_SET: Whether to confirm deploy change-set before executing it.
Ignored if ""PERFORM_DEPLOY"" is set to "false".
If set to "false", the ""deploy"" function deploys without displaying change-set.
Optional, defaults to "true".
- PERFORM_DESCRIBE_CHANGE_SET: Whether to perform the ""describe change-set"" sub-step independently.
The ""describe change-set"" sub-step is part of the ""deploy"" step if ""CONFIRM_CHANGE_SET"" is set to "true".
Parameter values for "package" function should be defined in the ""DESCRIBE_CHANGE_SET_PARAM_SECTION""
or ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"".
Should only be set to "true" if ""PERFORM_DEPLOY"" is set to "false"
because the ""deploy"" step already runs this sub-step after creating a change-set.
If "true", the change-set must already exist and "change_set_name" must be defined in either the
"CONFIG_ENV.describe_change_set.parameters", "CONFIG_ENV.deploy.parameters", or "CONFIG_ENV.global.parameters"
section of ""CONFIG_FILE"".
Optional, defaults to "false".
- PERFORM_EXECUTE_CHANGE_SET: Whether to perform the ""execute change-set"" sub-step independently.
The ""execute change-set"" sub-step is part of the ""deploy"" step.
Parameter values for "package" function should be defined in the ""EXECUTE_CHANGE_SET_PARAM_SECTION""
or ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"".
Should only be set to "true" if ""PERFORM_DEPLOY"" is set to "false"
because the ""deploy"" step already runs this sub-step after creating a change-set.
If "true", the change-set must already exist and "change_set_name" must be defined in either the
"CONFIG_ENV.describe_change_set.parameters", "CONFIG_ENV.deploy.parameters", or "CONFIG_ENV.global.parameters"
section of ""CONFIG_FILE"".
Optional, defaults to "false".
Usage Example:
CONDA_ENV=xxx
ARCHIVE_S3_BUCKET=xxx
wget -cO - "<this_file_url>" > "temp.sh"
chmod +x "temp.sh"
source "temp.sh" "$@"
rm -rf "temp.sh"
'
#--------------------------------------------
#----------------- CONSTANTS ----------------
#--------------------------------------------
CONDA_ENV="${CONDA_ENV}"
STOML_PATH=${STOML_PATH:-~/go/bin/stoml}
CONFIG_FILE="${CONFIG_FILE:-config.toml}"
CONFIG_ENV="${CONFIG_ENV:-default}"
ARCHIVE_S3_BUCKET="${ARCHIVE_S3_BUCKET}"
ARCHIVE_S3_BUCKET_REGION="${ARCHIVE_S3_BUCKET_REGION:-us-west-2}"
ARCHIVE_S3_BUCKET_TAGS=${ARCHIVE_S3_BUCKET_TAGS:-()}
PERFORM_CHECK=${PERFORM_CHECK:-true}
PERFORM_PACKAGE=${PERFORM_PACKAGE:-true}
PERFORM_DEPLOY=${PERFORM_DEPLOY:-true}
CONFIRM_CHANGE_SET=${CONFIRM_CHANGE_SET:-true}
PERFORM_DESCRIBE_CHANGE_SET=${PERFORM_DESCRIBE_CHANGE_SET:-false}
PERFORM_EXECUTE_CHANGE_SET=${PERFORM_EXECUTE_CHANGE_SET:-false}
#------- DO NOT EDIT BELOW THIS LINE --------
FORMAT_SCRIPT_URL="https://gist.githubusercontent.com/anniethiessen/efb6bc0e52ccfc8b330aa41364b53e97/raw/0012edc1f009a36d196f03f09fda68e70691860b/shell_script_essentials.sh"
FORMAT_SCRIPT_NAME="shell_script_essentials.sh"
GLOBAL_ENV_PRIMARY_CONFIG_SECTION="global"
GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION="global"
PACKAGE_COMMAND_SECONDARY_CONFIG_SECTION="package"
DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION="deploy"
DESCRIBE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION="describe_change_set"
EXECUTE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION="execute_change_set"
GLOBAL_TERTIARY_CONFIG_SECTION="global"
PARAMETER_TERTIARY_CONFIG_SECTION="parameters"
VALID_GLOBAL_COMMAND_PARAMS=("debug" "endpoint_url" "no_verify_ssl" "no_paginate" "output" "query" "profile" "region" "version" "color" "no_sign_request" "ca_bundle" "cli_read_timeout" "cli_connect_timeout")
VALID_PACKAGE_COMMAND_PARAMS=("template_file" "s3_bucket" "s3_prefix" "kms_key_id" "output_template_file" "use_json" "force_upload" "metadata")
VALID_DEPLOY_COMMAND_PARAMS=("template_file" "stack_name" "s3_bucket" "force_upload" "s3_prefix" "kms_key_id" "parameter_overrides" "capabilities" "no_execute_changeset" "disable_rollback" "no_disable_rollback" "role_arn" "notification_arns" "fail_on_empty_changeset" "no_fail_on_empty_changeset" "tags")
VALID_DESCRIBE_CHANGE_SET_COMMAND_PARAMS=("change_set_name" "stack_name" "cli_input_json" "starting_token" "max_items" "generate_cli_skeleton")
VALID_EXECUTE_CHANGE_SET_COMMAND_PARAMS=("change_set_name" "stack_name" "client_request_token" "disable_rollback" "no_disable_rollback" "retain_except_on_create" "no_retain_except_on_create" "cli_input_json" "generate_cli_skeleton")
BOOLEAN_PARAMS=("debug" "no_verify_ssl" "no_paginate" "no_sign_request" "use_json" "force_upload" "fail_on_empty_changeset" "no_fail_on_empty_changeset" "disable_rollback" "no_disable_rollback" "no_execute_changeset" "retain_except_on_create" "no_retain_except_on_create")
#--------------------------------------------
#--------------- FUNCTIONS -----------------
#--------------------------------------------
function run_format_script {
wget -cO - ${FORMAT_SCRIPT_URL} > ${FORMAT_SCRIPT_NAME}
chmod +x ${FORMAT_SCRIPT_NAME}
source ${FORMAT_SCRIPT_NAME} "$@"
rm -rf ${FORMAT_SCRIPT_NAME}
}
function get_aws_opts_from_config_file {
local opts param value primary_config_section secondary_config_section tertiary_config_section flag
local -n params=$1
local -n primary_config_sections=$2
local -n secondary_config_sections=$3
local -n tertiary_config_sections=$4
opts=""
for param in "${params[@]}"; do
value=""
for primary_config_section in "${primary_config_sections[@]}"; do
for secondary_config_section in "${secondary_config_sections[@]}"; do
for tertiary_config_section in "${tertiary_config_sections[@]}"; do
if [[ -z ${value} ]]; then
value=$( ${STOML_PATH} "${CONFIG_FILE}" "${primary_config_section}.${secondary_config_section}.${tertiary_config_section}.${param}" )
fi
done
done
done
if [[ -n ${value} ]]; then
flag=$( echo "--${param}" | sed "s/_/-/g" )
if [[ "${BOOLEAN_PARAMS[*]}" =~ (" "|^)${param}(" "|$) ]]; then
if [[ ${value} == "true" ]]; then opts+=" ${flag}"; fi
else
opts+=" ${flag} ${value}"
fi
fi
done
echo "${opts}"
}
function generate_s3_bucket_tags {
local tag_set tag tag_key tag_value tag_dict
tag_set=""
for tag in "${ARCHIVE_S3_BUCKET_TAGS[@]}" ; do
tag_key="${tag%%:*}"
tag_value="${tag##*:}"
tag_dict="{Key=${tag_key},Value=${tag_value}}"
tag_set="${tag_set}${tag_set:+,}${tag_dict}"
done
tag_set="[${tag_set}]"
echo "${tag_set}"
}
function check_s3_bucket {
local retval response
aws s3api head-bucket \
--bucket "${ARCHIVE_S3_BUCKET}" \
&> ${OUTPUT}
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_success_message "S3 bucket ${ARCHIVE_S3_BUCKET} exists."
else
output_error_message "S3 bucket ${ARCHIVE_S3_BUCKET} does not exist."
output_warning_message "Do you want to create S3 bucket ${S3_BUCKET}?"
select response in "Yes" "No"; do
case ${response} in
Yes ) create_s3_bucket; break;;
No ) exit_script;;
esac
done
fi
}
function create_s3_bucket {
local retval tag_set
aws s3 mb s3://"${ARCHIVE_S3_BUCKET}" \
--region "${ARCHIVE_S3_BUCKET_REGION}" \
&> ${OUTPUT}
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_success_message "S3 bucket ${ARCHIVE_S3_BUCKET} created."
else
output_error_message "S3 bucket ${ARCHIVE_S3_BUCKET} creation error." ${PROMPT_VERBOSE}
exit_script
fi
tag_set=$(generate_s3_bucket_tags)
aws s3api put-bucket-tagging \
--bucket "${ARCHIVE_S3_BUCKET}" \
--tagging "TagSet=${tag_set}" \
&> ${OUTPUT}
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_success_message "S3 bucket tag set ${tag_set} added."
else
output_error_message "S3 bucket tag set ${tag_set} add error." ${PROMPT_VERBOSE}
exit_script
fi
}
function check {
check_s3_bucket
}
function package {
local params primary_config_sections secondary_config_sections tertiary_config_sections opts retval
params=(`echo "${VALID_PACKAGE_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`)
primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}")
secondary_config_sections=("${PACKAGE_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}")
tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}")
opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" )
opts+=" --no-paginate"
output_info_message "Running 'package' command with options:"
output_info_message "${opts}"
aws cloudformation package ${opts} &> ${OUTPUT}
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_success_message "Stack packaged."
else
output_error_message "Stack packaging error." ${PROMPT_VERBOSE}
exit_script
fi
}
function describe_change_set {
local params primary_config_sections secondary_config_sections tertiary_config_sections opts change_set_name ret retval
params=(`echo "${VALID_DESCRIBE_CHANGE_SET_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`)
primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}")
secondary_config_sections=("${DESCRIBE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION}" "${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}")
tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}")
opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" )
opts+=" --no-paginate"
change_set_name=$1
if [[ -n ${change_set_name} ]]; then opts+=" --change-set-name ${change_set_name}"; fi
output_info_message "Running 'describe-change-set' command with options:"
output_info_message "${opts}"
ret=$( aws cloudformation describe-change-set ${opts} 2>&1 )
echo "${ret}"
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_info_message "Stack change-set described."
else
output_error_message "Stack change-set description error." ${PROMPT_VERBOSE}
exit_script
fi
}
function execute_change_set {
local params primary_config_sections secondary_config_sections tertiary_config_sections opts change_set_name retval
params=(`echo "${VALID_EXECUTE_CHANGE_SET_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`)
primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}")
secondary_config_sections=("${EXECUTE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION}" "${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}")
tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}")
opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" )
opts+=" --no-paginate"
change_set_name=$1
if [[ -n ${change_set_name} ]]; then opts+=" --change-set-name ${change_set_name}"; fi
output_info_message "Running 'execute-change-set' command with options:"
output_info_message "${opts}"
aws cloudformation execute-change-set ${opts} &> ${OUTPUT}
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_info_message "Stack change-set executed."
else
output_error_message "Stack change-set execution error." ${PROMPT_VERBOSE}
exit_script
fi
}
function deploy {
local params primary_config_sections secondary_config_sections tertiary_config_sections opts ret retval change_set_name stack_name response
params=(`echo "${VALID_DEPLOY_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`)
primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}")
secondary_config_sections=("${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}")
tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}")
opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" )
opts+=" --no-paginate"
if [[ "${CONFIRM_CHANGE_SET}" == "true" ]]; then
opts+=" --no-execute-changeset"
output_info_message "Running 'deploy' command with options:"
output_info_message "${opts}"
ret=$( aws cloudformation deploy ${opts} 2>&1 )
if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then echo "${ret}"; fi
change_set_name=$( awk -F"--change-set-name " '{print $2}' <<< "${ret}" )
change_set_name=$( echo "${change_set_name##*$'\n'}" )
change_set_name=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${change_set_name}" )
if [[ -z ${change_set_name} ]]; then
stack_name="${opts#*--stack-name }"
stack_name="${stack_name%% --*}"
no_change_ret=$( awk -F"No changes to deploy. " '{print $2}' <<< "${ret}" )
no_change_ret=$( echo "${no_change_ret##*$'\n'}" )
no_change_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${no_change_ret}" )
if [[ "${no_change_ret}" == "Stack ${stack_name} is up to date" ]]; then
output_info_message "No stack change-set to display."
exit_script 0
else
output_error_message "Stack change-set creation error." ${PROMPT_VERBOSE}
exit_script
fi
else
output_info_message "Stack change-set created."
describe_change_set "${change_set_name}"
output_question_message "Do you want to execute stack change-set ${change_set_name}?"
select response in "Yes" "No"; do
case ${response} in
Yes ) output_info_message "Executing stack change-set."; execute_change_set "${change_set_name}"; break;;
No ) output_info_message "Not executing stack change-set."; exit_script 0;;
esac
done
retval=$?
if [[ ${retval} -eq 0 ]]; then
output_success_message "Stack deployed."
else
output_error_message "Stack deployment error." ${PROMPT_VERBOSE}
exit_script
fi
fi
else
output_info_message "Running 'deploy' command with options:"
output_info_message "${opts}"
ret=$( aws cloudformation deploy ${opts} 2>&1 )
if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then echo "${ret}"; fi
stack_name="${opts#*--stack-name }"
stack_name="${stack_name%% --*}"
no_change_ret=$( awk -F"No changes to deploy. " '{print $2}' <<< "${ret}" )
no_change_ret=$( echo "${no_change_ret##*$'\n'}" )
no_change_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${no_change_ret}" )
if [[ "${no_change_ret}" == "Stack ${stack_name} is up to date" ]]; then
output_info_message "No stack change-set to deploy."
exit_script 0
fi
success_ret=$( awk -F"Successfully " '{print $2}' <<< "${ret}" )
success_ret=$( echo "${success_ret##*$'\n'}" )
success_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${success_ret}" )
if [[ "${success_ret}" != "created/updated stack - ${stack_name}" ]]; then
output_error_message "Stack deployment error." ${PROMPT_VERBOSE}
exit_script
else
output_success_message "Stack deployed."
fi
fi
}
#--------------------------------------------
#------------------ MAIN --------------------
#--------------------------------------------
run_format_script "$@"
if [ -n "${CONDA_ENV}" ]; then
eval "$(conda shell.bash hook)"
conda activate ${CONDA_ENV}
fi
if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then
PYTHON_VERSION=$( python --version 2>&1 )
AWSCLI_VERSION=$( aws --version 2>&1 )
output_warning_message "Using ${PYTHON_VERSION} and ${AWSCLI_VERSION}"
fi
output_header_message "----------------------------------------"
output_header_message "[1/3] CHECK"
output_header_message "checking required resources exist ..."
output_header_message "----------------------------------------"
if [ "${PERFORM_CHECK}" == true ] ; then
check
else output_warning_message "Checks skipped"; fi
output_header_message "----------------------------------------"
output_header_message "[2/3] PACKAGE"
output_header_message "packaging and uploading archive to S3 ..."
output_header_message "----------------------------------------"
if [ "${PERFORM_PACKAGE}" == true ] ; then
package
else output_warning_message "Package skipped"; fi
output_header_message "----------------------------------------"
output_header_message "[3/3] DEPLOY"
output_header_message "deploying stack to CloudFormation ..."
output_header_message "----------------------------------------"
if [ "${PERFORM_DEPLOY}" == true ] ; then
deploy
else output_warning_message "Deploy skipped"; fi
if [ "${PERFORM_DESCRIBE_CHANGE_SET}" == true ] ; then
output_header_message "----------------------------------------"
output_header_message "[3b/3] DESCRIBE CHANGE-SET"
output_header_message "describing existing change-set ..."
output_header_message "----------------------------------------"
describe_change_set
fi
if [ "${PERFORM_EXECUTE_CHANGE_SET}" == true ] ; then
output_header_message "----------------------------------------"
output_header_message "[3c/3] EXECUTE CHANGE-SET"
output_header_message "executing existing change-set ..."
output_header_message "----------------------------------------"
execute_change_set
fi
@anniethiessen
Copy link
Author

anniethiessen commented Oct 14, 2023

Known Issues:

v1:
-(#1) local: -n: invalid option errors, research shows its a bash<4.3 issue but still occurring on bash5.2
-(#2) awscli retvals are not totally dependable and some edge-case success/error messages may not be correct

v2:

@anniethiessen
Copy link
Author

anniethiessen commented Oct 15, 2023

TODO:

-add cloudformation validate step

@anniethiessen
Copy link
Author

anniethiessen commented Oct 26, 2023

Change Log:

v1: Initial

v2:
-Added CONDA_ENV variable: Conda environment is activated if defined

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment