chetan / invalidate-cloudfront-action

Invalidate AWS CloudFront distribution paths
MIT License
160 stars 36 forks source link

Enhancement Request - Max Attempts Parameter #16

Closed stevehaneytrailblazer closed 2 years ago

stevehaneytrailblazer commented 2 years ago

Hi. Not an issue, more of an enhancement request. I'm not proficient in Bash at all so I'm sure this would take you probably 5 minutes but occasionally the Cloudfront API seems to be a little spotty and unavailable.

I was looking at https://stackoverflow.com/a/73829744 and they mention a param AWS_MAX_ATTEMPTS= which I thought would be nice to be able to pass into this action as an option.

Any consideration would be welcome. Thanks!

stevehaneytrailblazer commented 2 years ago

Not sure if this would be acceptable...

#!/bin/bash -l

set -eo pipefail

# check configuration

err=0
$MAX_ATTEMPT_STR=""

if [ -z "$DISTRIBUTION" ]; then
  echo "error: DISTRIBUTION is not set"
  err=1
fi

if [[ -z "$PATHS" && -z "$PATHS_FROM" ]]; then
  echo "error: PATHS or PATHS_FROM is not set"
  err=1
fi

if [ -z "$AWS_ACCESS_KEY_ID" ]; then
  echo "error: AWS_ACCESS_KEY_ID is not set"
  err=1
fi

if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
  echo "error: AWS_SECRET_ACCESS_KEY is not set"
  err=1
fi

if [ -z "$AWS_REGION" ]; then
  echo "error: AWS_REGION is not set"
  err=1
fi

if [ $err -eq 1 ]; then
  exit 1
fi

if [ -n "$MAX_ATTEMPTS" ]; then
  $MAX_ATTEMPT_STR="AWS_MAX_ATTEMPTS=${MAX_ATTEMPTS}"
fi

# run

# Set it here to avoid logging keys/secrets
if [ "$DEBUG" = "1" ]; then
  echo "*** Enabling debug output (set -x)"
  set -x
fi

# Ensure we have jq-1.6
jq="jq"
if [[ ! -x "$(command -v $jq)" || "$($jq --version)" != "jq-1.6" ]]; then
  if [[ $(uname) == "Darwin" ]]; then
    jqbin="jq-osx-amd64"
  elif [[ $(uname) == "Linux" ]]; then
    jqbin="jq-linux64"
  fi
  if [[ -n "$jqbin" ]]; then
    jq="/usr/local/bin/jq16"
    wget -nv -O $jq https://github.com/stedolan/jq/releases/download/jq-1.6/$jqbin
    chmod 755 $jq
  fi
fi

if [[ -n "$PATHS_FROM" ]]; then
  echo "*** Reading PATHS from $PATHS_FROM"
  if [[ ! -f $PATHS_FROM ]]; then
    echo "PATHS file not found. nothing to do. exiting"
    exit 0
  fi
  PATHS=$(cat $PATHS_FROM | tr '\n' ' ')
  echo "PATHS=$PATHS"
  if [[ -z "$PATHS" ]]; then
    echo "PATHS is empty. nothing to do. exiting"
    exit 0
  fi
fi

# Handle multiple space-separated paths, particularly containing wildcards.
# i.e., if PATHS="/* /foo"
IFS=' ' read -r -a PATHS_ARR <<<"$PATHS"
echo -n "${PATHS}" >"${RUNNER_TEMP}/paths.txt"
JSON_PATHS=$($jq --null-input --compact-output --monochrome-output --rawfile inarr "${RUNNER_TEMP}/paths.txt" '$inarr | rtrimstr(" ") | rtrimstr("\n") | split(" ")')
LEN="${#PATHS_ARR[@]}"
CR="$(date +"%s")$RANDOM"
cat <<-EOF >"${RUNNER_TEMP}/invalidation-batch.json"
{ "InvalidationBatch": { "Paths": { "Quantity": ${LEN}, "Items": ${JSON_PATHS} }, "CallerReference": "${CR}" } }
EOF

if [ "$DEBUG" = "1" ]; then
  echo "> wrote ${RUNNER_TEMP}/invalidation-batch.json"
  cat "${RUNNER_TEMP}/invalidation-batch.json"
fi

# Support v1.x of the awscli which does not have this flag
[[ "$(aws --version)" =~ "cli/2" ]] && pagerflag="--no-cli-pager"
aws $pagerflag \
  $MAX_ATTEMPT_STR \
  cloudfront create-invalidation \
  --distribution-id "$DISTRIBUTION" \
  --cli-input-json "file://${RUNNER_TEMP}/invalidation-batch.json"
chetan commented 2 years ago

@stevehaneytrailblazer thanks for the suggestion. I think it may be possible to do this already without any changes. Just pass the extra env vars like so:

- name: Invalidate CloudFront
  uses: chetan/invalidate-cloudfront-action@v2
  env:
    DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
    PATHS: "/index.html"
    AWS_REGION: "us-east-1"
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    AWS_MAX_ATTEMPTS: "3"

You can likely pass any other vars supported by the CLI as well and it should just work. I don't have a good way to test the retries but will give it a shot and let you know.

chetan commented 2 years ago

@stevehaneytrailblazer Gave it a shot but I think it will only retry certain types of errors. Using an invalid distribution ID, for example, does not trigger a retry as the error returned is invalid permissions.

I'd say add the env var as above and see if your problem goes away. Feel free to re-open if you think there's something more I can do here.