Skip to content

Commit a931277

Browse files
Sc 28936 create a generic GitHub action to push frontend (#17)
* test action * test * Test each scenario * Adding inputs * change input * Finalizing inputs * Adding readme and removed echos * changed the env var * test github context * Debug * Accept pull request number as input * update readme * Added separate steps for upload and delete based on user input * Adding generic steps * Check for case * Bugfix with if statement * bugfix * bugfix * debug if statements * debug if statements * bugfix * Fixed bugs in expressions * Fixed exlude-files input * Update readme * Adding newline * Remove echos * Update exclude files logic Co-authored-by: Rashid N H M <[email protected]> * Implementing changes based on review Co-authored-by: Rashid N H M <[email protected]>
1 parent cf96005 commit a931277

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Action to push files to an S3 bucket to deploy a static web application
2+
3+
This action can be used to update a static web application that is built using AWS S3 and Cloudfront. The action pushes built code to an S3 bucket that already exists. One of the intended use cases for this action is Pull Request previews.
4+
5+
Files are pushed to the S3 bucket depending on the user inputs supplied when the action is called. Some inputs have default values or may be inferred from the github context.
6+
Following examples describe how to use the action.
7+
8+
## Uploading to S3 based on user input
9+
This example will **upload** the specified folder (`build-directory`) to a folder named `blog` on the S3 bucket(`myS3Bucket`). The action will not exclude any files while uploading them. The action will also invalidate the cloudfront cache.
10+
11+
```yaml
12+
- uses: XanaduAI/cloud-actions/push-to-s3-and-invalidate-cloudfront@main
13+
with:
14+
build-directory: build-dir
15+
pull-request-number: 123
16+
aws-cloudfront-distribution-id: ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }}
17+
aws-region: ${{ secrets.AWS_REGION }}
18+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
19+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
20+
s3-bucket: myS3Bucket
21+
s3-action: "upload"
22+
s3-dir-to-upload-to: "blog"
23+
s3-files-to-exclude: ""
24+
invalidate-cloudfront-cache: "true"
25+
```
26+
27+
## Deleting from S3 based on user input
28+
This example will **delete** the specified folder (`build-directory`) from the S3 bucket(`myS3Bucket`). The action will also invalidate the cloudfront cache.
29+
30+
```yaml
31+
- uses: XanaduAI/cloud-actions/push-to-s3-and-invalidate-cloudfront@main
32+
with:
33+
build-directory: build-dir
34+
pull-request-number: 123
35+
aws-cloudfront-distribution-id: ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }}
36+
aws-region: ${{ secrets.AWS_REGION }}
37+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
38+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
39+
s3-bucket: myS3Bucket
40+
s3-action: "delete"
41+
s3-dir-to-delete-from: "blog"
42+
invalidate-cloudfront-cache: "true"
43+
```
44+
45+
## Uploading/Deleting to/from S3 with minimal user unput
46+
If this action is called when a `pull_request` is `opened` or `syncronized`, then the example will **upload** the specified folder (`build-directory`) to a folder named `pr-previews/PR-123` on the S3 bucket (`myS3Bucket`). The action will exclude any files that start with the default `pr-previews` prefix. The action will not invalidate the cloudfront cache.
47+
48+
If this action is called when a `pull_request` is `closed`, then the example will **delete** the folder named `pr-previews/PR-123` on the S3 bucket (`myS3Bucket`).
49+
50+
```yaml
51+
- uses: XanaduAI/cloud-actions/push-to-s3-and-invalidate-cloudfront@main
52+
with:
53+
build-directory: build-dir
54+
pull-request-number: 123
55+
aws-cloudfront-distribution-id: ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }}
56+
aws-region: ${{ secrets.AWS_REGION }}
57+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
58+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
59+
s3-bucket: myS3Bucket
60+
```
61+
## AWS Permissions
62+
The IAM machine user needs the following permissions on the S3 bucket and the Cloudfront distribution:
63+
```
64+
s3:ListBucket
65+
s3:GetObject
66+
s3:PutObject
67+
s3:DeleteObject
68+
cloudfront:CreateInvalidation
69+
```
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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

Comments
 (0)