I set some quick automation for publishing the site. I’m storing things in a GitHub Repo so I went ahead and setup a GitHub Workflow to build and publish the site.
To get things rolling I first had to setup an AWS IAM Identity Provider and an AWS IAM Role. I’m still managing all of this via the AWS Console and the creation wizards are much better then they were. I was able to step through the process and only need to make one manual change. I updated the IAM Role’s Trust Policy to enable Session Tagging, the policy created by the wizard did not have the sts:TagSession
action included. The walkthrough in the GitHub Docs is a great place to start: Configuring OpenID Connect in Amazon Web Services.
Updated IAM Role Trust Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "<iam_identity_provider_arn>"
},
"Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<repo_owner>/<repo_name>:*"
}
}
}
]
}
I created GitHub Repository Secrets for:
- The ARN of the IAM Role created via the AWS Console Wizard
- The S3 Bucket Name
- The Cloudfront Distribution ID
From there I setup a GitHub Workflow triggered by a push to my repo’s main
branch.
GitHub Workflow
name: Publish Site
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build_publish:
name: Build and Publish
permissions:
id-token: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Hugo
shell: pwsh
run: |
$GithubRequestHeaders = @{
Accept = "application/vnd.github.v3+json"
"X-GitHub-Api-Version" = "2022-11-28"
}
Invoke-WebRequest -Uri "https://api.github.com/repos/gohugoio/hugo/releases/latest" -Headers $GithubRequestHeaders | ConvertFrom-Json `
| Select-Object -ExpandProperty assets `
| Where-Object { $_.name -like "hugo_extended_*_linux-amd64.tar*" } `
| Select-Object -ExpandProperty browser_download_url | ForEach-Object {
$DownloadPath = Join-Path -Path "./" -ChildPath $(Split-Path -Leaf $_)
$output = "$(Get-Location)/$(Split-Path -Leaf $_)"
$tarFile = (Split-Path -Leaf $_).Replace(".gz", "")
Invoke-WebRequest -Uri $_ -OutFile $DownloadPath
tar -xzf $DownloadPath -C $(Get-Location)
New-Item -ItemType Directory -Path "$Env:RUNNER_TEMP/hugo_bin" -Force
Move-Item -Path "./hugo" -Destination "$Env:RUNNER_TEMP/hugo_bin/hugo"
}
"$Env:RUNNER_TEMP/hugo_bin" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Build Site
shell: pwsh
run: |
npm install
hugo --cleanDestinationDir --environment production --verbose
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-2
role-to-assume: ${{ secrets.AWS_PUBLISH_SITE_ROLE }}
- name: Publish Site
shell: pwsh
run: |
cd public
aws s3 sync ./ s3://${{ secrets.SITE_S3_BUCKET }}/${{ github.run_id }}/ --delete
aws s3 sync ./ s3://${{ secrets.SITE_S3_BUCKET }}/live/ --delete
aws cloudfront create-invalidation --distribution-id ${{ secrets.SITE_CLOUDFRONT_DISTRO }} --paths "/*"
Some next steps are to:
- Selectively push only new/updated files to the
live
prefix - Create a
setup-hugo
GitHub Action - Add Cache Control Headers as part of the upload to S3 to more easily manage cache settings
- Setup the ability to view versions of the site not in
live
based on subdomain or path or something