Skip to content

Commit 704b85a

Browse files
jnfclaude
andcommitted
feat: add static app config and deploy workflow
tofu/configs/static/ instantiates the static-app module following the same pattern as configs/docs/: a locals.tf discovers app specs from apps/*.yaml, appspec modules parse them, and the static module wires everything together. .github/workflows/deploy-static.yml is a reusable workflow_call target. Apps call it by passing AWS_STATIC_ROLE_ARN (secret) and STATIC_BUCKET + STATIC_PREFIX (vars). CLOUDFRONT_DISTRIBUTION_ID is optional — if set, the workflow invalidates the prefix after sync. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e02a8d0 commit 704b85a

5 files changed

Lines changed: 101 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Deploy static app
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
environment:
7+
description: Environment to deploy to.
8+
required: false
9+
default: development
10+
type: string
11+
source_dir:
12+
description: Local directory to sync (relative to repo root).
13+
required: false
14+
default: "."
15+
type: string
16+
17+
permissions:
18+
contents: read
19+
id-token: write
20+
21+
jobs:
22+
deploy:
23+
name: Deploy to ${{ inputs.environment }}
24+
environment: ${{ inputs.environment }}
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v6
28+
- name: Configure AWS credentials
29+
uses: aws-actions/configure-aws-credentials@v5
30+
with:
31+
aws-region: ${{ vars.AWS_REGION || 'us-east-1' }}
32+
role-session-name: github-${{ github.event.repository.name }}-${{ github.run_id }}
33+
role-to-assume: ${{ secrets.AWS_STATIC_ROLE_ARN }}
34+
- name: Sync to S3
35+
run: |
36+
aws s3 sync "${{ inputs.source_dir }}" \
37+
"s3://${{ vars.STATIC_BUCKET }}/${{ vars.STATIC_PREFIX }}" \
38+
--delete \
39+
--exclude ".git/*" \
40+
--exclude ".github/*"
41+
- name: Invalidate CloudFront cache
42+
if: vars.CLOUDFRONT_DISTRIBUTION_ID != ''
43+
run: |
44+
aws cloudfront create-invalidation \
45+
--distribution-id "${{ vars.CLOUDFRONT_DISTRIBUTION_ID }}" \
46+
--paths "/${{ vars.STATIC_PREFIX }}/*"

tofu/configs/static/apps/.gitkeep

Whitespace-only changes.

tofu/configs/static/locals.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
locals {
2+
specs = toset([for f in fileset("${path.module}/apps", "*.yaml") : replace(f, ".yaml", "")])
3+
}

tofu/configs/static/main.tf

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
terraform {
2+
backend "s3" {
3+
bucket = "shared-services-${var.environment}-tfstate"
4+
key = "static.tfstate"
5+
region = "us-east-1"
6+
dynamodb_table = "${var.environment}.tfstate"
7+
}
8+
}
9+
10+
module "appspec" {
11+
source = "../../modules/appspec"
12+
for_each = local.specs
13+
14+
spec_path = "${abspath(path.module)}/apps/${each.value}.yaml"
15+
}
16+
17+
module "inputs" {
18+
source = "github.com/codeforamerica/tofu-modules-aws-ssm-inputs?ref=1.0.0"
19+
20+
prefix = "/shared-services/${var.environment}"
21+
inputs = ["logging/bucket", "vpc/id"]
22+
}
23+
24+
module "static" {
25+
source = "../../modules/static-app"
26+
27+
environment = var.environment
28+
bucket_name = "apps.${var.environment == "production" ? "services.cfa.codes" : "dev.services.cfa.codes"}"
29+
force_delete = var.environment != "production"
30+
domain = var.environment == "production" ? "services.cfa.codes" : "dev.services.cfa.codes"
31+
subdomain = "apps"
32+
apps = module.appspec
33+
logging_bucket = module.inputs.values["logging/bucket"]
34+
vpc_id = module.inputs.values["vpc/id"]
35+
}

tofu/configs/static/variables.tf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
variable "environment" {
2+
type = string
3+
description = "Deployment environment for static app resources."
4+
default = "development"
5+
}
6+
7+
variable "program" {
8+
type = string
9+
description = "Name of the program the static apps project belongs to."
10+
default = "engineering"
11+
}
12+
13+
variable "project" {
14+
type = string
15+
description = "Name of the static apps project."
16+
default = "cfa-static-apps"
17+
}

0 commit comments

Comments
 (0)