|
| 1 | +name: Push files to an S3 bucket destination and invalidate the cloudfront cache |
| 2 | +description: | |
| 3 | + This action will push files to a destination S3 bucket (or a folder within a bucket) and invalidates the cloudfront cache. |
| 4 | + The action also removes any stale files from the bucket. The action can also delete files/folders from the bucket. |
| 5 | +
|
| 6 | +inputs: |
| 7 | + build-directory: |
| 8 | + description: The directory that contains the build files to upload to S3 |
| 9 | + required: true |
| 10 | + aws-cloudfront-distribution-id: |
| 11 | + description: The cloudfront distribution ID for the app |
| 12 | + required: true |
| 13 | + aws-region: |
| 14 | + description: The aws region used by the IAM machine user |
| 15 | + required: true |
| 16 | + aws-access-key-id: |
| 17 | + description: The aws access key id for the IAM machine user |
| 18 | + required: true |
| 19 | + aws-secret-access-key: |
| 20 | + description: The aws secret access key for the IAM machine user |
| 21 | + required: true |
| 22 | + s3-bucket: |
| 23 | + description: The name of the S3 bucket |
| 24 | + required: true |
| 25 | + |
| 26 | + pull-request-number: |
| 27 | + description: The pull request number for which a preview needs to be generated/updated. This is required if you do not specify the s3-directory variable. |
| 28 | + required: false |
| 29 | + s3-action: |
| 30 | + description: | |
| 31 | + The action to take on the S3 bucket. Typically this should be `update` to push the latest files to S3 or `delete` to delete the folder from S3. |
| 32 | + If this is not specified, the action will be infered from the $github.event.action variable |
| 33 | + required: false |
| 34 | + default: "" |
| 35 | + s3-directory: |
| 36 | + description: | |
| 37 | + The S3 directory to upload the files to or delete the files from. If unspecified, the default `PR-$pull-request-number` will be used |
| 38 | + or the directory may be infered from the github context. A value of `/` indicates the root of the bucket. |
| 39 | + required: false |
| 40 | + default: "pr-previews" |
| 41 | + s3-files-to-exclude: |
| 42 | + description: | |
| 43 | + A pattern or a comma separated list of files to exclude when running the aws s3 sync command. |
| 44 | + Refer to https://docs.aws.amazon.com/cli/latest/reference/s3/index.html#use-of-exclude-and-include-filters or more information |
| 45 | + Set this variable to an empty string if you don't want to exlcude any files |
| 46 | + If unspecified will default to `pr-previews/*` |
| 47 | + required: false |
| 48 | + default: "pr-previews/*" |
| 49 | + invalidate-cloudfront-cache: |
| 50 | + description: A flag to indicate if the cloudfront cache should be invalidated |
| 51 | + required: false |
| 52 | + default: "false" |
| 53 | + |
| 54 | +outputs: |
| 55 | + dir_name: |
| 56 | + description: The S3 directory to upload the files to or delete files from. Computed based on user input. |
| 57 | + value: ${{ steps.directory.dir_name }} |
| 58 | + files_to_exlude: |
| 59 | + description: Files to exclude from S3 when using the sync command. |
| 60 | + value: ${{ steps.exclude.files_to_exclude }} |
| 61 | + |
| 62 | +runs: |
| 63 | + using: composite |
| 64 | + steps: |
| 65 | + - name: Input validation for pull-request-number |
| 66 | + if: inputs.s3-directory == 'pr-previews' && inputs.pull-request-number == '' |
| 67 | + uses: actions/github-script@v6 |
| 68 | + with: |
| 69 | + script: | |
| 70 | + core.setFailed('Either of the pull-request-number or the s3-directory are required') |
| 71 | + |
| 72 | + - name: Compute the S3 directory to upload to or delete from |
| 73 | + shell: bash |
| 74 | + id: directory |
| 75 | + run: | |
| 76 | + if [[ "${{ inputs.s3-directory }}" == "pr-previews" ]] |
| 77 | + then |
| 78 | + dir_name="${{ inputs.s3-directory }}/PR-${{ inputs.pull-request-number }}" |
| 79 | + elif [[ "${{ inputs.s3-directory }}" == "/" ]] |
| 80 | + then |
| 81 | + dir_name="" |
| 82 | + else |
| 83 | + dir_name="${{ inputs.s3-directory }}" |
| 84 | + fi |
| 85 | + echo "dir_name=$dir_name" >> $GITHUB_OUTPUT |
| 86 | +
|
| 87 | + - name: Compute files to exclude |
| 88 | + shell: bash |
| 89 | + id: exclude |
| 90 | + run: | |
| 91 | + files_to_exlude="" |
| 92 | + if [[ "${{ inputs.s3-files-to-exclude }}" == *,* ]] |
| 93 | + then |
| 94 | + IFS=',' |
| 95 | + for i in `echo "${{ inputs.s3-files-to-exclude }}"` |
| 96 | + do |
| 97 | + files_to_exlude="$files_to_exlude --exclude \"$i\"" |
| 98 | + done |
| 99 | + unset IFS |
| 100 | + elif [[ "${{ inputs.s3-files-to-exclude }}" != "" ]] |
| 101 | + then |
| 102 | + files_to_exlude="--exclude \"${{ inputs.s3-files-to-exclude }}\"" |
| 103 | + fi |
| 104 | + echo "files_to_exlude=$files_to_exlude" >> $GITHUB_OUTPUT |
| 105 | +
|
| 106 | + - name: Upload the files to S3 |
| 107 | + shell: bash |
| 108 | + if: inputs.s3-action == 'upload' || (inputs.s3-action == '' && github.event_name == 'pull_request' && contains(fromJson('["opened", "synchronize"]'), github.event.action)) |
| 109 | + env: |
| 110 | + AWS_REGION: ${{ inputs.aws-region }} |
| 111 | + AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} |
| 112 | + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} |
| 113 | + run: | |
| 114 | + aws s3 sync ${{ inputs.build-directory }}/ s3://${{ inputs.s3-bucket }}/${{ steps.directory.outputs.dir_name }} ${{ steps.exclude.outputs.files_to_exlude }} |
| 115 | +
|
| 116 | + - name: Delete the files on S3 |
| 117 | + shell: bash |
| 118 | + if: inputs.s3-action == 'delete' || (inputs.s3-action == '' && github.event_name == 'pull_request' && github.event.action == 'closed') |
| 119 | + env: |
| 120 | + AWS_REGION: ${{ inputs.aws-region }} |
| 121 | + AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} |
| 122 | + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} |
| 123 | + run: aws s3 rm s3://${{ inputs.s3-bucket }}/${{ steps.directory.outputs.dir_name }}/ --recursive ${{ steps.exclude.outputs.files_to_exlude }} |
| 124 | + |
| 125 | + - name: Invalidate the cloudfront cache |
| 126 | + shell: bash |
| 127 | + if: inputs.invalidate-cloudfront-cache == 'true' |
| 128 | + env: |
| 129 | + AWS_REGION: ${{ inputs.aws-region }} |
| 130 | + AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} |
| 131 | + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} |
| 132 | + run: | |
| 133 | + aws cloudfront create-invalidation --distribution-id ${{ inputs.aws-cloudfront-distribution-id }} --paths "/${{ steps.directory.outputs.dir_name }}/*" |
0 commit comments