diff --git a/README.md b/README.md index ee3852a..863d829 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,9 @@ The following inputs can be used as `step.with` keys | `aws_site_cdn_aliases` | String | Extra CNAMEs (alternate domain names), if any, for this distribution. Defaults to defined domain if none passed. (See note). | | `aws_site_cdn_custom_error_codes` | JSON | Custom error codes to define in CDN. Like `[{\"error_caching_min_ttl\":\"0\",\"error_code\":\"403\",\"response_code\":\"200\",\"response_page_path\":\"/index.html\"}]`. See [this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution.html#custom-error-response-arguments). | | `aws_site_cdn_response_headers_policy_id` | String | Comma separated list of response headers policy IDs for CloudFront. Eg. `Managed-CORS-with-preflight-and-SecurityHeadersPolicy` is `eaab4381-ed33-4a86-88ca-d9558dc6cd63`. | +| `aws_site_cdn_min_ttl` | Number | Minimum TTL (in seconds) for CloudFront cache. Default is `0`. | +| `aws_site_cdn_default_ttl` | Number | Default TTL (in seconds) for CloudFront cache. (CloudFront default is `86400` - 24 hours), but defaults to `0` (disabled) | +| `aws_site_cdn_max_ttl` | Number | Maximum TTL (in seconds) for CloudFront cache. (CloudFront default is `31536000` 365 days), but defaults to `0` (disabled). |

@@ -243,6 +246,23 @@ If that's the case, `aws_site_cdn_aliases` should be set to: `site.bitovi.com,si If they alternate domain names are child of the same domain, you can use a root cert for both. +## CloudFront Caching + +For deployments or applications that rotate files on each deployment, the default cache TTL settings help ensure a smooth transition between deployments: + +- **`aws_site_cdn_default_ttl`**: Set to 24 hours (86400 seconds) +- **`aws_site_cdn_max_ttl`**: Set to 365 days (31536000 seconds) + +These settings allow CloudFront to cache files even after they've been deleted from S3, reducing 404 errors during deployment transitions. Files remain cached at edge locations for the specified TTL period, giving users time to gradually transition to the new version. + +Example with custom TTL settings: +```yaml +aws_site_cdn_enabled: true +aws_site_cdn_min_ttl: 0 +aws_site_cdn_default_ttl: 172800 # 48 hours +aws_site_cdn_max_ttl: 604800 # 7 days +``` + ## Contributing We would love for you to contribute to [bitovi/github-actions-deploy-static-site-to-aws](https://github.com/bitovi/github-actions-deploy-static-site-to-aws). Would you like to see additional features? [Create an issue](https://github.com/bitovi/github-actions-deploy-static-site-to-aws/issues/new) or a [Pull Requests](https://github.com/bitovi/github-actions-deploy-static-site-to-aws/pulls). We love discussing solutions! diff --git a/action.yaml b/action.yaml index 3d96fd8..f9d8a48 100644 --- a/action.yaml +++ b/action.yaml @@ -76,6 +76,15 @@ inputs: aws_site_cdn_response_headers_policy_id: description: 'Comma separated list of response headers policy IDs for CloudFront. Eg. Managed-CORS-with-preflight-and-SecurityHeadersPolicy is 67f7725c-6f97-4210-82d7-5512b31e9d42.' required: false + aws_site_cdn_min_ttl: + description: 'Minimum TTL (in seconds) for CloudFront cache. Default is 0.' + required: false + aws_site_cdn_default_ttl: + description: 'Default TTL (in seconds) for CloudFront cache. Default is 86400 (24 hours).' + required: false + aws_site_cdn_max_ttl: + description: 'Maximum TTL (in seconds) for CloudFront cache. Default is 31536000 (365 days).' + required: false # AWS Route53 Domains and Certificates aws_r53_domain_name: @@ -140,6 +149,9 @@ runs: AWS_SITE_CDN_ALIASES: ${{ inputs.aws_site_cdn_aliases }} AWS_SITE_CDN_CUSTOM_ERROR_CODES: ${{ inputs.aws_site_cdn_custom_error_codes }} AWS_SITE_CDN_RESPONSE_HEADERS_POLICY_ID: ${{ inputs.aws_site_cdn_response_headers_policy_id }} + AWS_SITE_CDN_MIN_TTL: ${{ inputs.aws_site_cdn_min_ttl }} + AWS_SITE_CDN_DEFAULT_TTL: ${{ inputs.aws_site_cdn_default_ttl }} + AWS_SITE_CDN_MAX_TTL: ${{ inputs.aws_site_cdn_max_ttl }} # AWS Route53 Domains abd Certificates AWS_R53_DOMAIN_NAME: ${{ inputs.aws_r53_domain_name }} AWS_R53_SUB_DOMAIN_NAME: ${{ inputs.aws_r53_sub_domain_name }} diff --git a/scripts/generate_deploy.sh b/scripts/generate_deploy.sh index 1740b6a..9bb1eb4 100755 --- a/scripts/generate_deploy.sh +++ b/scripts/generate_deploy.sh @@ -98,6 +98,9 @@ aws_site_cdn_enabled=$(generate_var aws_site_cdn_enabled $AWS_SITE_CDN_ENABLED) aws_site_cdn_aliases=$(generate_var aws_site_cdn_aliases $AWS_SITE_CDN_ALIASES) aws_site_cdn_custom_error_codes=$(generate_var aws_site_cdn_custom_error_codes $AWS_SITE_CDN_CUSTOM_ERROR_CODES) aws_site_cdn_response_headers_policy_id=$(generate_var aws_site_cdn_response_headers_policy_id $AWS_SITE_CDN_RESPONSE_HEADERS_POLICY_ID) +aws_site_cdn_min_ttl=$(generate_var aws_site_cdn_min_ttl $AWS_SITE_CDN_MIN_TTL) +aws_site_cdn_default_ttl=$(generate_var aws_site_cdn_default_ttl $AWS_SITE_CDN_DEFAULT_TTL) +aws_site_cdn_max_ttl=$(generate_var aws_site_cdn_max_ttl $AWS_SITE_CDN_MAX_TTL) aws_site_root_object=$(generate_var aws_site_root_object $AWS_SITE_ROOT_OBJECT) aws_site_error_document=$(generate_var aws_site_error_document $AWS_SITE_ERROR_DOCUMENT) aws_r53_domain_name=$(generate_var aws_r53_domain_name $AWS_R53_DOMAIN_NAME) @@ -121,6 +124,9 @@ $aws_site_cdn_enabled $aws_site_cdn_aliases $aws_site_cdn_custom_error_codes $aws_site_cdn_response_headers_policy_id +$aws_site_cdn_min_ttl +$aws_site_cdn_default_ttl +$aws_site_cdn_max_ttl $aws_site_root_object $aws_site_error_document $aws_r53_domain_name diff --git a/terraform_code/main.tf b/terraform_code/main.tf index 609d9a1..2633a61 100644 --- a/terraform_code/main.tf +++ b/terraform_code/main.tf @@ -156,9 +156,9 @@ resource "aws_cloudfront_distribution" "cdn_static_site_default_cert" { } default_cache_behavior { - min_ttl = 0 - default_ttl = 0 - max_ttl = 0 + min_ttl = var.aws_site_cdn_min_ttl + default_ttl = var.aws_site_cdn_default_ttl + max_ttl = var.aws_site_cdn_max_ttl viewer_protocol_policy = "redirect-to-https" allowed_methods = ["GET", "HEAD", "OPTIONS"] @@ -212,9 +212,9 @@ resource "aws_cloudfront_distribution" "cdn_static_site" { } default_cache_behavior { - min_ttl = 0 - default_ttl = 0 - max_ttl = 0 + min_ttl = var.aws_site_cdn_min_ttl + default_ttl = var.aws_site_cdn_default_ttl + max_ttl = var.aws_site_cdn_max_ttl viewer_protocol_policy = "redirect-to-https" allowed_methods = ["GET", "HEAD", "OPTIONS"] diff --git a/terraform_code/variables.tf b/terraform_code/variables.tf index f3eb5c2..da279e0 100644 --- a/terraform_code/variables.tf +++ b/terraform_code/variables.tf @@ -67,6 +67,24 @@ variable "aws_site_cdn_response_headers_policy_id" { default = "" } +variable "aws_site_cdn_min_ttl" { + description = "Minimum amount of time (in seconds) that objects stay in CloudFront cache before CloudFront forwards another request to the origin. Default is 0." + type = number + default = 0 +} + +variable "aws_site_cdn_default_ttl" { + description = "Default amount of time (in seconds) that an object is in a CloudFront cache before CloudFront forwards another request to the origin. Default is 86400 (24 hours)." + type = number + default = 0 +} + +variable "aws_site_cdn_max_ttl" { + description = "Maximum amount of time (in seconds) that an object is in a CloudFront cache before CloudFront forwards another request to the origin. Default is 31536000 (365 days)." + type = number + default = 0 +} + variable "aws_r53_domain_name" { description = "root domain name without any subdomains" type = string