Deploying a Jekyll Page to AWS S3 with GH Actions
Tags: actionshackathon, aws
Published: 2020-09-05 08:59:03

[Instructions]: # (To submit to the GitHub Actions x DEV Hackathon, please fill out all sections.)


### My Workflow
The name of my workflow is: jekyll-build-deploy-aws-s3-cloudfront

My workflow builds a jekyll page, uploads it to a AWS S3 bucket
and creates an invalidation for AWS CloudFront with a custom python script.
As part of the #ActionsHackathon i made some improvements on the Workflow .yml itself and also on the custom invalidation file creator written in python.

Although there exists some GH Actions which can be used to create CloudFront invalidations none of theme satisfied me. 
In future I also plan to release my own GH Action which uses this python script.

I use this workflow for the webpage of a project which raises funds for children in Kenia.
{% github https://github.com/mrxder/WebsiteMalaika %}
[Note]: # (Make sure to include the name of your GitHub Action and share where it's being used!)


### Submission Category: 
DIY Deployments

[Note]: # (Maintainer Must-Haves, DIY Deployments, Interesting IoT, Phone Friendly, or Wacky Wildcards)


### Yaml File or Link to Code
This is the Action Workflow
```yml
name: jekyll-buld-deploy-aws-s3-cloudfront

on:
  push:
    branches: [master]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - uses: actions/setup-ruby@v1
        with:
          ruby-version: "2.6"

      - uses: actions/setup-python@v2
        with:
          python-version: "3.x"

      - uses: chrislennon/action-aws-cli@v1.1

      - name: Build and deploy
        run: |
          rm -f Gemfile.lock
          bundle install
          bundle exec jekyll build
          aws s3 sync _site s3://<S3 bucket>
          python3 create_invalidation_json.py _site > invbatch.json
          aws cloudfront create-invalidation --distribution-id <distribution id> --invalidation-batch file://invbatch.json
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: <AWS Region>

```

This is the custom invalidation script:
```python
from os import listdir
from os.path import isfile, isdir, join
from urllib.parse import quote
from datetime import datetime
import sys
import random


def recursive_file_lister(root_path, actual_path, all_files):

    full_path_of_dir = join(root_path, actual_path)

    content_of_dir = listdir(full_path_of_dir)

    for i in content_of_dir:

        full_path_of_file = (join(root_path, actual_path, i))
        relative_path_of_file = (join(actual_path, i))

        if isfile(full_path_of_file):
            aws_path_for_file = quote("/"+relative_path_of_file)
            all_files.append(aws_path_for_file)
        elif isdir(full_path_of_file):
            recursive_file_lister(root_path, relative_path_of_file, all_files)


def create_json_for_invalidation(all_files, refernece):

    print("{")
    print(" \"Paths\": {")
    print("     \"Quantity\":", str(len(all_files))+",")
    print("     \"Items\": [")

    for i in range(len(all_files)):
        if(i < (len(all_files)-1)):
            print("         \""+all_files[i]+"\",")
        else:
            print("         \""+all_files[i]+"\"")
    print("     ]")
    print("   },")
    print("  \"CallerReference\": \""+refernece+"\"")
    print("}")


if len(sys.argv) != 2:
    print("Usage")
    print("create_invalidation_json.py dir")
else:
    all_files = ["/"]
    recursive_file_lister(sys.argv[1], "", all_files)

    create_json_for_invalidation(all_files, "auto_deploy_script_"+str(
        datetime.now().strftime("%I_%M%p_%B_%d_%Y_"))+str(random.randint(1, 999999999999)))

```

[Note]: # (Our markdown editor supports pretty embeds. Try this syntax: `{% github link_to_your_repo %}` to share a GitHub repository)


### Additional Resources / Info
This Action Workflow is used by the malaika homepage:
[Malaika](https://github.com/mrxder/WebsiteMalaika)

[Note]: # (Be sure to link to any open source projects that are using your workflow!)

[Reminder]: # (Submissions are due on September 12th (11:59 PM PDT) and winners will be announced on September 23!)