Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scheduled task for send grant digest emails #2890

Merged
merged 9 commits into from
Apr 4, 2024

Conversation

jeffsmohan
Copy link
Contributor

@jeffsmohan jeffsmohan commented Mar 31, 2024

Ticket #2133

Description

Adds a scheduled ECS task to send grant digest emails. A flag is introduced to switch from the old sending infrastructure (crons set up on our API boxes) over to the new scheduled ECS task.

The previous implementation was causing a couple problems:

  1. Since we're running 2 API boxes in production, the cron was kicked off twice and users were receiving duplicates of the grant digest emails.
  2. Running the send digest email task on our API boxes (both of them at the same time) would cause the servers to be somewhat unresponsive to normal web requests every morning while the digest emails were being sent.

This solution is meant to be a short-term fix. A more robust solution will require re-architecting the email infrastructure more broadly to support a task queue for individual emails, clear email send retries, dead letter queues, etc.

Additional context and discussion can be found in:

Note to reviewer:

  • Recommend turning off whitespace in the Github diff view, as it'll make clearer what's changed in some of the tf blocks
  • I left a couple implementation questions inline as comments

Screenshots / Demo Video

Testing

  • Added automated unit tests
  • We'll need to actually run a test of this in staging, since it's prohibitively difficult to test the terraform scheduled task setup in development

Automated and Unit Tests

  • Added Unit tests

Manual tests for Reviewer

  • Added steps to test feature/functionality manually

Checklist

  • Provided ticket and description
  • Provided screenshots/demo
  • Provided testing information
  • Provided adequate test coverage for all new code
  • Added PR reviewers

@github-actions github-actions bot added Infra Issues related to the infrastructure underlying all the tools. javascript Pull requests that update Javascript code terraform Pull requests that update Terraform code labels Mar 31, 2024
Copy link

github-actions bot commented Mar 31, 2024

QA Summary

QA Check Result
🌐 Client Tests
🔗 Server Tests
🤝 E2E Tests
📏 ESLint
🧹 TFLint

Test Coverage

Coverage report for `packages/client`
St File % Stmts % Branch % Funcs % Lines Uncovered Line #s
🔴 All files 16.71 14.87 20.96 16.95
🟡  ...nents/src/arpa_reporter/components 50.9 26.66 60.52 50.9
🔴   AlertBox.vue 0 0 0 0 35-36
🟡   DownloadButton.vue 50 50 42.85 50 60-67
🟢   DownloadFileButton.vue 100 100 100 100
🟢   DownloadTemplateBtn.vue 100 100 100 100
🟡   PageNavigation.vue 63.15 100 62.5 63.15 213-219,228-235
🔴   StandardForm.vue 34.78 20 55.55 34.78 124-128,135-157
🟢  arpa_reporter/helpers 84.61 79.48 87.5 84.61
🟢   form-helpers.js 84.21 79.48 85.71 84.21 7,16,25,81-83
🟢   short-uuid.js 100 100 100 100
🔴  arpa_reporter/store 4.85 0 2.17 5.1
🔴   index.js 4.85 0 2.17 5.1 13-16,34-263
🔴  ...rter/views/src/arpa_reporter/views 38.69 30.5 69.69 38.69
🟢   AgenciesView.vue 100 100 100 100
🔴   HomeView.vue 14.28 0 50 14.28 113,137-207
🔴   UploadView.vue 48.21 50 78.94 48.21 ...41-442,448-449
🔴   UploadsView.vue 43.18 38.88 66.66 43.18 ...65-268,276-291
🔴   UserView.vue 38.7 28.57 68.75 38.7 84,97-137
🔴  ...nents/Modals/src/components/Modals 4.95 2.17 9.09 4.97
🔴   AddOrganization.vue 7.69 0 14.28 7.69 139-170
🔴   AddTeam.vue 41.17 33.33 60 41.17 200,206,212-235
🔴   EditOrganization.vue 11.11 0 16.66 11.11 58-78
🔴   EditTeam.vue 5.12 0 16.66 5.12 193,206-299
🔴   GrantDetailsLegacy.vue 0 0 0 0 205-369
🔴   ImportTeams.vue 0 0 0 0 56-82
🔴   ProfileSettings.vue 0 0 0 0 57-136
🔴   SavedSearchPanel.vue 0 0 0 0 146-256
🔴   SearchPanel.vue 1.75 0 0 1.78 301-487
🔴  components/src/components 4.86 3.77 9.85 4.86
🔴   ActivityTable.vue 0 0 0 0 110-179
🟡   BaseLayout.vue 50 66.66 53.84 50 285-300
🔴   ClosingDatesTable.vue 0 0 0 0 56-88
🔴   GrantsTable.vue 3.1 0 0 3.1 187-543
🔴   RecordUploader.vue 0 0 0 0 54-107
🔴   SearchFilter.vue 0 0 0 0 40-82
🔴   UserAvatar.vue 0 0 0 0 29-40
🔴  helpers 17.54 18.94 16.66 18.01
🟢   constants.js 100 100 100 100
🟢   currency.js 100 100 100 100
🟢   dates.js 100 100 100 100
🔴   fetchApi.js 5.55 12.5 5.55 5.55 10-102
🔴   filters.js 4 0 0 4.54 19-51
🔴   form-helpers.js 0 0 0 0 5-82
🟡   gtag.js 77.77 90 75 77.77 12,51
🟢  helpers/featureFlags 100 100 100 100
🟢   index.js 100 100 100 100
🟢   utils.js 100 100 100 100
🔴  mixin 23.8 0 28.57 23.8
🔴   resizableTable.js 23.8 0 28.57 23.8 16-31,36-37,42
🔴  router 20 11.53 17.64 20
🔴   index.js 20 11.53 17.64 20 ...74-175,179-198
🟢  store 100 100 100 100
🟢   index.js 100 100 100 100
🔴  store/modules 5.88 0 4.7 6.13
🔴   agencies.js 10 100 8.33 10.52 13-70
🔴   alerts.js 20 100 20 20 10-24
🔴   dashboard.js 4.65 0 4.54 4.65 22-96
🔴   grants.js 2.79 0 1.05 2.94 59-353
🔴   organization.js 33.33 100 33.33 33.33 21-25
🔴   roles.js 33.33 100 20 40 13-22
🔴   tenants.js 20 100 14.28 22.22 13-32
🔴   users.js 4.76 0 4.76 4.87 17-100
🟡  views 50 100 0 50
🟡   NotFoundView.vue 50 100 0 50 2-4
🔴  views/src/views 14.89 0 26 14.89
🔴   ArpaAnnualPerformanceReporter.vue 0 0 0 0 81-134
🔴   DashboardView.vue 26.31 0 36.36 26.31 ...30-140,158-169
🔴   LoginView.vue 0 0 0 0 76-128
🔴   OrganizationsView.vue 40 100 40 40 84,94-97,111-115
🟡   TeamsView.vue 50 100 50 50 142,156-163
Coverage report for `packages/server`
St File % Stmts % Branch % Funcs % Lines Uncovered Line #s
🟡 All files 55.17 46.89 49.86 55.54
🟢  src 82.35 33.33 60 82.35
🟢   configure.js 82.35 33.33 60 82.35 44,63-70,99-101
🟢  src/arpa_reporter 98.75 66.66 100 98.75
🟢   configure.js 97.36 40 100 97.36 36
🟢   environment.js 100 100 100 100
🟢   use-request.js 100 100 100 100
🔴  src/arpa_reporter/db 38.58 32.92 44.44 40.16
🔴   arpa-subrecipients.js 13.15 4.34 15.38 14.28 23-92
🔴   reporting-periods.js 37.2 46.87 40 38.09 46,77-156
🟢   settings.js 100 83.33 100 100 13
🟡   uploads.js 50 28.57 52.38 51.42 18-29,83,98-123,140-149
🔴  src/arpa_reporter/lib 25.43 20.8 26.38 25.64
🟢   arpa-ec-codes.js 100 100 100 100
🔴   audit-report.js 23.14 20.68 27.77 22.65 ...78-479,505-635,683-709
🟡   ensure-async-context.js 75 100 50 100
🔴   format.js 13.79 0 0 19.04 28-82
🟡   log.js 75 50 50 75 13,25
🟡   preconditions.js 66.66 33.33 100 66.66 3
🔴   spreadsheet.js 9.09 0 0 9.09 15-32
🟢   validation-error.js 85.71 100 50 85.71 16
🔴  src/arpa_reporter/routes 40.08 14.92 14.28 40.69
🔴   agencies.js 22.58 0 0 23.33 13-21,26-53
🟡   application_settings.js 75 100 0 75 10-11
🟡   audit-report.js 69.86 58.33 100 69.86 57-58,64-78,100-115
🟢   exports.js 81.42 83.33 100 81.42 61-75,98-99
🔴   reporting-periods.js 20 0 0 20.43 ...25-137,143-149,154-180
🔴   subrecipients.js 23.8 0 0 23.8 12-13,17-27,31-48,52-63
🔴   uploads.js 28.28 7.89 9.09 29.16 ...33-154,164-166,173-180
🔴   users.js 19.6 0 0 20 15-35,39-44,48-81
🔴  src/arpa_reporter/services 42.52 30.12 45.39 42.89
🔴   generate-arpa-report.js 36.86 2.79 50 37.24 ...-944,953-966,1040-1107
🔴   get-template.js 21.62 0 0 21.62 18-79
🟡   persist-upload.js 68.6 90 69.56 68.67 ...58-200,221-235,273-295
🔴   records.js 20.75 0 11.11 21.15 38-204,221-276
🔴   revalidate-uploads.js 37.5 100 0 37.5 5-14
🔴   validate-upload.js 37.93 49.41 32.14 38.83 ...10,329,351,369-658,673
🟢   validation-rules.js 98.18 90 90.9 100 157,173
🟡  src/db 75.41 72.27 69.94 75.51
🟢   connection.js 100 50 100 100 6
🟢   constants.js 100 100 100 100
🟢   helpers.js 83.33 100 50 83.33 21-22
🟢   index.js 83.18 78.61 82.87 83.17 ...05-1571,1753-1754,1761
🟢   saved_search_migration.js 92 88.23 71.42 93.61 5,69,134
🔴   tenant_creation.js 10.58 2.7 0 11.11 15-40,48-210,220
🔴  src/db/arpa_reporter_db_shims 23.68 0 0 23.68
🔴   agencies.js 22.22 100 0 22.22 11-51
🔴   users.js 25 0 0 25 12-62
🟡  src/lib 66.5 62.71 62.1 67.4
🟢   access-helpers.js 93.44 89.18 100 93.44 91-92,97-98
🟢   agencyImporter.js 90.38 88.46 100 90.19 26,29,35,93-94
🔴   batchProcessor.js 2.94 0 0 3.03 35-104
🟢   email.js 91.19 77.77 100 91.02 ...33,176,318-321,358-359
🔴   gost-aws.js 21.05 11.11 20 19.44 13-58,65-116
🟢   grants-ingest.js 83.33 97.5 90 83.33 ...28-131,138-140,155-159
🔴   grantsgov.js 6.25 6.52 0 6.97 12-220
🟡   logging.js 77.77 85.71 100 77.77 11,13
🟢   redirect_validation.js 100 100 100 100
🟢   userImporter.js 82.27 58.33 88.88 81.57 32,47,53,62,73-81,143-152
🔴  src/lib/annualReports 27.38 0 0 27.38
🔴   doc-builder.js 7.69 0 0 7.69 19-352
🟡   index.js 80 100 0 80 6
🟢   placeholderTextStrings.js 100 100 100 100
🔴   reportBuilder.js 17.24 0 0 17.24 21-33,50-62,86-103
🟢  src/lib/arpa_reporter_shims 100 100 100 100
🟢   email.js 100 100 100 100
🟢  src/lib/email 92.85 87.5 100 92.3
🟢   constants.js 100 100 100 100
🟢   email-nodemailer.js 88.23 83.33 100 86.66 33,59
🟢   service-email.js 100 100 100 100
🟢  src/lib/fieldConfigs 100 100 100 100
🟢   fundingActivityCategories.js 100 100 100 100
🔴  src/lib/grantscraper 11.86 0 0 12.96
🔴   index.js 11.86 0 0 12.96 11-92,98-122
🟡  src/routes 68.36 57.52 60.49 68.43
🔴   agencies.js 45.54 30 40 45.54 ...33-141,145-166,174-180
🔴   annualReports.js 47.05 100 0 47.05 15-27
🔴   dashboard.js 21.42 0 0 21.42 8-53
🟢   eligibilityCodes.js 100 100 100 100
🟢   grants.js 80.43 71.02 73.52 81.25 ...80-381,396-399,412-413
🟡   grantsSavedSearch.js 80 83.33 100 80 38-39,56-57,70-72,78
🟢   health.js 100 100 100 100
🟡   interestedCodes.js 71.42 100 0 71.42 7-8
🟢   keywords.js 86.95 50 100 86.95 26-27,34
🟡   refresh.js 71.42 100 0 71.42 7-8
🟡   roles.js 75 100 0 75 8-9
🟡   searchConfig.js 58.33 100 0 58.33 9-14
🟡   sessions.js 63.93 39.39 50 63.93 ...-73,79-80,84-85,98-104
🔴   tenants.js 39.13 0 0 39.13 11-12,16-27,32-35
🟢   users.js 80.41 74.19 85.71 80.41 ...17,134-136,160,169-177
🟢  src/scripts 87.5 87.5 66.66 93.33
🟢   sendGrantDigestEmail.js 87.5 87.5 66.66 93.33 32

Pusher: @TylerHendrickson, Action: pull_request_target, Workflow: Continuous Integration

Copy link

github-actions bot commented Mar 31, 2024

Terraform Summary

Step Result
🖌 Terraform Format & Style
⚙️ Terraform Initialization
🤖 Terraform Validation
📖 Terraform Plan

Hint: If "Terraform Format & Style" failed, run terraform fmt -recursive from the terraform/ directory and commit the results.

Output

Validation Output
Success! The configuration is valid.


Plan Output
Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the
last "terraform apply" which may have affected this plan:

  # module.api.aws_ecs_task_definition.default[0] has changed
  ~ resource "aws_ecs_task_definition" "default" {
        id                       = "gost-staging-api"
+       tags                     = {}
        # (13 unchanged attributes hidden)

+       volume {
+           name = "data"

+           efs_volume_configuration {
+               file_system_id          = "fs-08f95063c1cdbe191"
+               root_directory          = "/"
+               transit_encryption      = "ENABLED"
+               transit_encryption_port = 0

+               authorization_config {
+                   access_point_id = "fsap-03bc0296928aade4f"
                }
            }
        }
-       volume {
-           name = "data" -> null

-           efs_volume_configuration {
-               file_system_id     = "fs-08f95063c1cdbe191" -> null
-               root_directory     = "/" -> null
-               transit_encryption = "ENABLED" -> null

-               authorization_config {
-                   access_point_id = "fsap-03bc0296928aade4f" -> null
                }
            }
        }

        # (1 unchanged block hidden)
    }

  # module.api.aws_iam_role.task[0] has changed
  ~ resource "aws_iam_role" "task" {
        id                    = "gost-staging-api-ECSTask-2023021701041477300000000a"
        name                  = "gost-staging-api-ECSTask-2023021701041477300000000a"
      ~ role_last_used        = [
          ~ {
              ~ last_used_date = "2024-04-04T15:48:28Z" -> "2024-04-04T18:11:53Z"
                # (1 unchanged element hidden)
            },
        ]
        tags                  = {}
        # (11 unchanged attributes hidden)

        # (6 unchanged blocks hidden)
    }


Unless you have made equivalent changes to your configuration, or ignored the
relevant attributes using ignore_changes, the following plan may include
actions to undo or respond to these changes.

─────────────────────────────────────────────────────────────────────────────

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+   create
  ~ update in-place
-   destroy
+/- create replacement and then destroy
 <= read (data resources)

Terraform will perform the following actions:

  # module.api.aws_ecs_service.default[0] will be updated in-place
  ~ resource "aws_ecs_service" "default" {
        id                                 = "arn:aws:ecs:us-west-2:357150818708:service/gost-staging/gost-staging-api"
        name                               = "gost-staging-api"
        tags                               = {}
      ~ task_definition                    = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-api:219" -> (known after apply)
        # (15 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # module.api.aws_ecs_task_definition.default[0] must be replaced
+/- resource "aws_ecs_task_definition" "default" {
      ~ arn                      = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-api:219" -> (known after apply)
      ~ arn_without_revision     = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-api" -> (known after apply)
      ~ container_definitions    = jsonencode(
          ~ [ # forces replacement
              ~ {
                  ~ dockerLabels           = {
                      ~ "com.datadoghq.tags.version" = "9570e4ac4ce3c34fe658606b07425a9097c366b1" -> "bcafb3eb8a101a31853f76a46f2f8c7844e04cf4"
                        # (2 unchanged elements hidden)
                    }
                  ~ environment            = [
                        # (7 unchanged elements hidden)
                        {
                            name  = "DD_SERVICE"
                            value = "gost"
                        },
                      ~ {
                            name  = "DD_VERSION"
                          ~ value = "9570e4ac4ce3c34fe658606b07425a9097c366b1" -> "bcafb3eb8a101a31853f76a46f2f8c7844e04cf4"
                        },
                        {
                            name  = "ENABLE_GRANTS_DIGEST"
                            value = "false"
                        },
                        {
                            name  = "ENABLE_GRANTS_SCRAPER"
                            value = "false"
                        },
+                       {
+                           name  = "ENABLE_GRANT_DIGEST_SCHEDULED_TASK"
+                           value = "true"
                        },
                        {
                            name  = "ENABLE_MY_PROFILE"
                            value = "true"
                        },
                        # (10 unchanged elements hidden)
                    ]
                  ~ image                  = "ghcr.io/usdigitalresponse/usdr-gost-api:9570e4ac4ce3c34fe658606b07425a9097c366b1@sha256:ba6bcacab6b1152fe7067f5bb1c1712862e32ecfcfa00980fe6f86c7b3aae0d1" -> "ghcr.io/usdigitalresponse/usdr-gost-api:bcafb3eb8a101a31853f76a46f2f8c7844e04cf4@sha256:caac8cb9c28583e24b4e1bb5e4bfaff848459093cfa81bac450f5a8a8861f51f"
                    name                   = "api"
-                   systemControls         = [] -> null
-                   volumesFrom            = [] -> null
                    # (9 unchanged elements hidden)
                } # forces replacement,
              ~ {
                  ~ dockerLabels           = {
                      ~ "com.datadoghq.tags.version" = "9570e4ac4ce3c34fe658606b07425a9097c366b1" -> "bcafb3eb8a101a31853f76a46f2f8c7844e04cf4"
                        # (2 unchanged elements hidden)
                    }
                  ~ environment            = [
                        # (3 unchanged elements hidden)
                        {
                            name  = "DD_SERVICE"
                            value = "gost"
                        },
                      ~ {
                            name  = "DD_VERSION"
                          ~ value = "9570e4ac4ce3c34fe658606b07425a9097c366b1" -> "bcafb3eb8a101a31853f76a46f2f8c7844e04cf4"
                        },
                        {
                            name  = "ECS_FARGATE"
                            value = "true"
                        },
                    ]
-                   mountPoints            = [] -> null
                    name                   = "datadog"
-                   portMappings           = [] -> null
-                   systemControls         = [] -> null
-                   volumesFrom            = [] -> null
                    # (6 unchanged elements hidden)
                } # forces replacement,
            ]
        )
      ~ id                       = "gost-staging-api" -> (known after apply)
      ~ revision                 = 219 -> (known after apply)
-       tags                     = {} -> null
        # (9 unchanged attributes hidden)

-       volume {
-           name = "data" -> null

-           efs_volume_configuration {
-               file_system_id          = "fs-08f95063c1cdbe191" -> null
-               root_directory          = "/" -> null
-               transit_encryption      = "ENABLED" -> null
-               transit_encryption_port = 0 -> null

-               authorization_config {
-                   access_point_id = "fsap-03bc0296928aade4f" -> null
                }
            }
        }
+       volume {
+           name = "data"

+           efs_volume_configuration {
+               file_system_id     = "fs-08f95063c1cdbe191"
+               root_directory     = "/"
+               transit_encryption = "ENABLED"

+               authorization_config {
+                   access_point_id = "fsap-03bc0296928aade4f"
                }
            }
        }

        # (1 unchanged block hidden)
    }

  # module.arpa_audit_report.aws_ecs_service.default will be updated in-place
  ~ resource "aws_ecs_service" "default" {
        id                                 = "arn:aws:ecs:us-west-2:357150818708:service/gost-staging/gost-staging-arpa_audit_report"
        name                               = "gost-staging-arpa_audit_report"
        tags                               = {}
      ~ task_definition                    = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-arpa_audit_report:188" -> (known after apply)
        # (15 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.arpa_audit_report.aws_ecs_task_definition.consumer must be replaced
+/- resource "aws_ecs_task_definition" "consumer" {
      ~ arn                      = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-arpa_audit_report:188" -> (known after apply)
      ~ arn_without_revision     = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-arpa_audit_report" -> (known after apply)
      ~ container_definitions    = (sensitive value) # forces replacement
      ~ id                       = "gost-staging-arpa_audit_report" -> (known after apply)
-       ipc_mode                 = "" -> null
-       pid_mode                 = "" -> null
      ~ revision                 = 188 -> (known after apply)
-       tags                     = {} -> null
        # (9 unchanged attributes hidden)

-       volume {
-           name = "data" -> null

-           efs_volume_configuration {
-               file_system_id          = "fs-08f95063c1cdbe191" -> null
-               root_directory          = "/" -> null
-               transit_encryption      = "ENABLED" -> null
-               transit_encryption_port = 0 -> null

-               authorization_config {
-                   access_point_id = "fsap-03bc0296928aade4f" -> null
                }
            }
        }
+       volume {
+           name = "data"

+           efs_volume_configuration {
+               file_system_id     = "fs-08f95063c1cdbe191"
+               root_directory     = "/"
+               transit_encryption = "ENABLED"

+               authorization_config {
+                   access_point_id = "fsap-03bc0296928aade4f"
                }
            }
        }

        # (1 unchanged block hidden)
    }

  # module.arpa_treasury_report.aws_ecs_service.default will be updated in-place
  ~ resource "aws_ecs_service" "default" {
        id                                 = "arn:aws:ecs:us-west-2:357150818708:service/gost-staging/gost-staging-treasury_report"
        name                               = "gost-staging-treasury_report"
        tags                               = {}
      ~ task_definition                    = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-treasury_report:177" -> (known after apply)
        # (15 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.arpa_treasury_report.aws_ecs_task_definition.consumer must be replaced
+/- resource "aws_ecs_task_definition" "consumer" {
      ~ arn                      = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-treasury_report:177" -> (known after apply)
      ~ arn_without_revision     = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-treasury_report" -> (known after apply)
      ~ container_definitions    = (sensitive value) # forces replacement
      ~ id                       = "gost-staging-treasury_report" -> (known after apply)
-       ipc_mode                 = "" -> null
-       pid_mode                 = "" -> null
      ~ revision                 = 177 -> (known after apply)
-       tags                     = {} -> null
        # (9 unchanged attributes hidden)

-       volume {
-           name = "data" -> null

-           efs_volume_configuration {
-               file_system_id          = "fs-08f95063c1cdbe191" -> null
-               root_directory          = "/" -> null
-               transit_encryption      = "ENABLED" -> null
-               transit_encryption_port = 0 -> null

-               authorization_config {
-                   access_point_id = "fsap-03bc0296928aade4f" -> null
                }
            }
        }
+       volume {
+           name = "data"

+           efs_volume_configuration {
+               file_system_id     = "fs-08f95063c1cdbe191"
+               root_directory     = "/"
+               transit_encryption = "ENABLED"

+               authorization_config {
+                   access_point_id = "fsap-03bc0296928aade4f"
                }
            }
        }

        # (1 unchanged block hidden)
    }

  # module.consume_grants.aws_ecs_service.default will be updated in-place
  ~ resource "aws_ecs_service" "default" {
        id                                 = "arn:aws:ecs:us-west-2:357150818708:service/gost-staging/gost-staging-consume_grants"
        name                               = "gost-staging-consume_grants"
        tags                               = {}
      ~ task_definition                    = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-consume_grants:204" -> (known after apply)
        # (15 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

  # module.consume_grants.aws_ecs_task_definition.consume_grants must be replaced
+/- resource "aws_ecs_task_definition" "consume_grants" {
      ~ arn                      = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-consume_grants:204" -> (known after apply)
      ~ arn_without_revision     = "arn:aws:ecs:us-west-2:357150818708:task-definition/gost-staging-consume_grants" -> (known after apply)
      ~ container_definitions    = (sensitive value) # forces replacement
      ~ id                       = "gost-staging-consume_grants" -> (known after apply)
-       ipc_mode                 = "" -> null
-       pid_mode                 = "" -> null
      ~ revision                 = 204 -> (known after apply)
-       tags                     = {} -> null
        # (9 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

  # module.website.aws_s3_object.deploy-config[0] will be updated in-place
  ~ resource "aws_s3_object" "deploy-config" {
      ~ content                = <<-EOT
            window.APP_CONFIG = window.APP_CONFIG || {};
            window.APP_CONFIG.apiURLForGOST = 'https://api.staging.grants.usdr.dev/';
            window.apiURLForGOST = window.APP_CONFIG.apiURLForGOST; // Legacy
            
            window.APP_CONFIG.DD_RUM_ENABLED = true;
-           window.APP_CONFIG.DD_RUM_CONFIG = {"allowedTracingUrls":["https://api.staging.grants.usdr.dev"],"applicationId":"15db471e-2ccb-4d3c-a6bf-99b750d748f5","clientToken":"pub50834fcc1999d53e546519b1a0f03934","defaultPrivacyLevel":"mask","env":"staging","service":"gost","sessionReplaySampleRate":100,"sessionSampleRate":100,"site":"datadoghq.com","trackLongTasks":true,"trackResources":true,"trackUserInteractions":true,"version":"9570e4ac4ce3c34fe658606b07425a9097c366b1"};
+           window.APP_CONFIG.DD_RUM_CONFIG = {"allowedTracingUrls":["https://api.staging.grants.usdr.dev"],"applicationId":"15db471e-2ccb-4d3c-a6bf-99b750d748f5","clientToken":"pub50834fcc1999d53e546519b1a0f03934","defaultPrivacyLevel":"mask","env":"staging","service":"gost","sessionReplaySampleRate":100,"sessionSampleRate":100,"site":"datadoghq.com","trackLongTasks":true,"trackResources":true,"trackUserInteractions":true,"version":"bcafb3eb8a101a31853f76a46f2f8c7844e04cf4"};
            
            window.APP_CONFIG.GOOGLE_TAG_ID = 'G-D5DFR7BN0N';
            
            window.APP_CONFIG.featureFlags = {"myProfileEnabled":true,"newGrantsDetailPageEnabled":true,"newTerminologyEnabled":true};
            
            window.APP_CONFIG.overrideFeatureFlag = (flagName, overrideValue) => {
              const storageKey = 'featureFlags';
              let overrides = {};
              try {
                overrides = JSON.parse(window.sessionStorage.getItem(storageKey)) || {};
              } catch (e) {
                console.error(`Error parsing window.sessionStorage.${storageKey} as JSON:`, e);
                console.warn(`window.sessionStorage.${storageKey} will be replaced.`);
              }
              overrides[flagName] = overrideValue;
              window.sessionStorage.setItem(storageKey, JSON.stringify(overrides));
              console.log('New feature flag overrides in page session:',
                window.sessionStorage.getItem(storageKey));
            };
        EOT
      ~ etag                   = "4aef77e321070b6ed0bbfbd32f746243" -> "5bfe7bcf66dda02dee1d86692b7a64dc"
        id                     = "/config/deploy-config.js"
        tags                   = {}
      ~ version_id             = "XJMdlehJ3r8dc3.0h3CXZnEm21nnmjLH" -> (known after apply)
        # (10 unchanged attributes hidden)
    }

  # module.website.aws_s3_object.origin_dist_artifact["arpa_reporter/index.html"] will be updated in-place
  ~ resource "aws_s3_object" "origin_dist_artifact" {
      ~ etag                   = "c3e5f47627117bdd48669ce3fdb6f4f8" -> "04471d83e92eeab3a96d11d39c1e36ba"
        id                     = "dist/arpa_reporter/index.html"
      ~ source_hash            = "c3e5f47627117bdd48669ce3fdb6f4f8" -> "04471d83e92eeab3a96d11d39c1e36ba"
        tags                   = {}
      ~ version_id             = "RV07As3f47rJ_rENoKtKgWO_eiqZSVcT" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # module.website.aws_s3_object.origin_dist_artifact["index.html"] will be updated in-place
  ~ resource "aws_s3_object" "origin_dist_artifact" {
      ~ etag                   = "2459933fd5096eefbc551703f6e6b938" -> "ad1b945931c7d5af98960a2ffd8a19eb"
        id                     = "dist/index.html"
      ~ source_hash            = "2459933fd5096eefbc551703f6e6b938" -> "ad1b945931c7d5af98960a2ffd8a19eb"
        tags                   = {}
      ~ version_id             = "if.Rci58UYoKYzddiYinjhYaSBwmGTs4" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/131.33a64a4c.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "86f2af2941f01afd805ee2584d1713af"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/131.33a64a4c.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/131.33a64a4c.js"
+       source_hash            = "86f2af2941f01afd805ee2584d1713af"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/131.33a64a4c.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "104d6236fc9b514b39361aa1f3ac039c"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/131.33a64a4c.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/131.33a64a4c.js.map"
+       source_hash            = "104d6236fc9b514b39361aa1f3ac039c"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/131.7e57803b.js"] will be destroyed
  # (because key ["js/131.7e57803b.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "40dacfaebf4825ca990c5724fab5cf89" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/131.7e57803b.js" -> null
-       key                    = "dist/js/131.7e57803b.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/131.7e57803b.js" -> null
-       source_hash            = "40dacfaebf4825ca990c5724fab5cf89" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "kOAbTMfhZL7VT.Ixl3_Wf7gbnDa8a.n7" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/131.7e57803b.js.map"] will be destroyed
  # (because key ["js/131.7e57803b.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "1046ebe65a7434e1bf16bd71236e3a3c" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/131.7e57803b.js.map" -> null
-       key                    = "dist/js/131.7e57803b.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/131.7e57803b.js.map" -> null
-       source_hash            = "1046ebe65a7434e1bf16bd71236e3a3c" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "Azm832nJkxHhZz6xq9BxzQ.4.WmC979O" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/223.66070969.js"] will be destroyed
  # (because key ["js/223.66070969.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "08d1e6c73b3c861a908e83216ed3f235" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/223.66070969.js" -> null
-       key                    = "dist/js/223.66070969.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/223.66070969.js" -> null
-       source_hash            = "08d1e6c73b3c861a908e83216ed3f235" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = ".QLzanuR_TJbwq8ER2rCloiLE.aWH8Gb" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/223.66070969.js.map"] will be destroyed
  # (because key ["js/223.66070969.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "ad6f6fe4d5db3549891b86157dbcbafe" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/223.66070969.js.map" -> null
-       key                    = "dist/js/223.66070969.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/223.66070969.js.map" -> null
-       source_hash            = "ad6f6fe4d5db3549891b86157dbcbafe" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "_ouPUynLoI9hfvRh5r1TrGgpfQcM4vlC" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/223.8de88314.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "c049d3ec4778a0d311364cfe8f741717"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/223.8de88314.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/223.8de88314.js"
+       source_hash            = "c049d3ec4778a0d311364cfe8f741717"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/223.8de88314.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "79da56b101d6293a71582ecf7ae8c3aa"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/223.8de88314.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/223.8de88314.js.map"
+       source_hash            = "79da56b101d6293a71582ecf7ae8c3aa"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/40.e3b39a73.js"] will be destroyed
  # (because key ["js/40.e3b39a73.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "314e23405be700293f93db6fcba52c8e" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/40.e3b39a73.js" -> null
-       key                    = "dist/js/40.e3b39a73.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/40.e3b39a73.js" -> null
-       source_hash            = "314e23405be700293f93db6fcba52c8e" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "GinWJxdWahpCnRWwO5ntB7upRsXtV4Zm" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/40.e3b39a73.js.map"] will be destroyed
  # (because key ["js/40.e3b39a73.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "40458df830450598c35aff95f3fdaa08" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/40.e3b39a73.js.map" -> null
-       key                    = "dist/js/40.e3b39a73.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/40.e3b39a73.js.map" -> null
-       source_hash            = "40458df830450598c35aff95f3fdaa08" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "5faiAMbshSx5qdYob14jY3sUGa5DJ3wN" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/40.fd397793.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "463452d5aef2bb901f99124f7f7972db"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/40.fd397793.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/40.fd397793.js"
+       source_hash            = "463452d5aef2bb901f99124f7f7972db"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/40.fd397793.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "671fc25c833a02b62a5cd1681ed0eb82"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/40.fd397793.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/40.fd397793.js.map"
+       source_hash            = "671fc25c833a02b62a5cd1681ed0eb82"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/439.0f32e7b9.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "186e713662a85b47be8db6ef7bceec86"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/439.0f32e7b9.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/439.0f32e7b9.js"
+       source_hash            = "186e713662a85b47be8db6ef7bceec86"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/439.0f32e7b9.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "61a06399be80b34f0205afda74c352ad"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/439.0f32e7b9.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/439.0f32e7b9.js.map"
+       source_hash            = "61a06399be80b34f0205afda74c352ad"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/439.87b42fb3.js"] will be destroyed
  # (because key ["js/439.87b42fb3.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "d75d3b2544f8532cfc322ccb364647f9" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/439.87b42fb3.js" -> null
-       key                    = "dist/js/439.87b42fb3.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/439.87b42fb3.js" -> null
-       source_hash            = "d75d3b2544f8532cfc322ccb364647f9" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "OUm0WOorH1AK9nEZ5u6FqT0BfnNa.eBC" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/439.87b42fb3.js.map"] will be destroyed
  # (because key ["js/439.87b42fb3.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "b0ab2d386a2bc54c85d955583c91e206" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/439.87b42fb3.js.map" -> null
-       key                    = "dist/js/439.87b42fb3.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/439.87b42fb3.js.map" -> null
-       source_hash            = "b0ab2d386a2bc54c85d955583c91e206" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "ge5Kccz56z_yD5_ArlQS_YP6T5C2k4nE" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/466.96b8d902.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "85804da8691112d28c32fdbb86bc8107"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/466.96b8d902.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/466.96b8d902.js"
+       source_hash            = "85804da8691112d28c32fdbb86bc8107"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/466.96b8d902.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "fc7852fa86a4bf92f58e491f7c83fa60"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/466.96b8d902.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/466.96b8d902.js.map"
+       source_hash            = "fc7852fa86a4bf92f58e491f7c83fa60"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/466.f8c953fb.js"] will be destroyed
  # (because key ["js/466.f8c953fb.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "536a8166375f0c95cd8b0b9f8c4206e5" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/466.f8c953fb.js" -> null
-       key                    = "dist/js/466.f8c953fb.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/466.f8c953fb.js" -> null
-       source_hash            = "536a8166375f0c95cd8b0b9f8c4206e5" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "CUwL8gQO1_q7bV.ACkwgM7RSzsdJPvNj" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/466.f8c953fb.js.map"] will be destroyed
  # (because key ["js/466.f8c953fb.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "fef5dce20f471e20c591909ff4861690" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/466.f8c953fb.js.map" -> null
-       key                    = "dist/js/466.f8c953fb.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/466.f8c953fb.js.map" -> null
-       source_hash            = "fef5dce20f471e20c591909ff4861690" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "jCwYMwwBSa2TAu00GkQP8MlfKonztSx9" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/582.4a7ec86d.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "e3dc8b0a51ace8aae3552b8ec7aec7ad"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/582.4a7ec86d.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/582.4a7ec86d.js"
+       source_hash            = "e3dc8b0a51ace8aae3552b8ec7aec7ad"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/582.4a7ec86d.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "a2b9a49fef57fd5c3448430ec7ddb3b0"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/582.4a7ec86d.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/582.4a7ec86d.js.map"
+       source_hash            = "a2b9a49fef57fd5c3448430ec7ddb3b0"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/582.f56b76ea.js"] will be destroyed
  # (because key ["js/582.f56b76ea.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "1719648aad688ad159bfd589f947db3d" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/582.f56b76ea.js" -> null
-       key                    = "dist/js/582.f56b76ea.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/582.f56b76ea.js" -> null
-       source_hash            = "1719648aad688ad159bfd589f947db3d" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "qG6QlV_R61N2Qg9ZTy6qhUCZJlMme1K6" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/582.f56b76ea.js.map"] will be destroyed
  # (because key ["js/582.f56b76ea.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "f3034a30d3f75c286f403efa6f098730" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/582.f56b76ea.js.map" -> null
-       key                    = "dist/js/582.f56b76ea.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/582.f56b76ea.js.map" -> null
-       source_hash            = "f3034a30d3f75c286f403efa6f098730" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "yKRaMHme.SHLwFg5pEE71lAfxxhJfWsq" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/584.e774c3a3.js"] will be destroyed
  # (because key ["js/584.e774c3a3.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "28730918e703f33feead039c35694f22" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/584.e774c3a3.js" -> null
-       key                    = "dist/js/584.e774c3a3.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/584.e774c3a3.js" -> null
-       source_hash            = "28730918e703f33feead039c35694f22" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "YJAAAeRHMFYpPkOKL60CJ49QJl9558B7" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/584.e774c3a3.js.map"] will be destroyed
  # (because key ["js/584.e774c3a3.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "e20c2824ca4887e438bf419d0e6f0d54" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/584.e774c3a3.js.map" -> null
-       key                    = "dist/js/584.e774c3a3.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/584.e774c3a3.js.map" -> null
-       source_hash            = "e20c2824ca4887e438bf419d0e6f0d54" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "GLaVQXSzd1Via1C2.DpgLdk69BgJdH39" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/584.fb3d0916.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "052d047c5ac30a6e99c6b3c1610a2f61"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/584.fb3d0916.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/584.fb3d0916.js"
+       source_hash            = "052d047c5ac30a6e99c6b3c1610a2f61"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/584.fb3d0916.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "5762c39c4ef3a72e6d679e07bab38e3b"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/584.fb3d0916.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/584.fb3d0916.js.map"
+       source_hash            = "5762c39c4ef3a72e6d679e07bab38e3b"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/605.aa684f31.js"] will be destroyed
  # (because key ["js/605.aa684f31.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "text/javascript" -> null
-       etag                   = "375548178672ce20db132cb4331a6b79" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/605.aa684f31.js" -> null
-       key                    = "dist/js/605.aa684f31.js" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/605.aa684f31.js" -> null
-       source_hash            = "375548178672ce20db132cb4331a6b79" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "FpLSzjODRazgEj.tsFW04t9aheLg6gqW" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/605.aa684f31.js.map"] will be destroyed
  # (because key ["js/605.aa684f31.js.map"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_enabled     = false -> null
-       content_type           = "application/json" -> null
-       etag                   = "c758bea9d097d4d40418afa74f514643" -> null
-       force_destroy          = false -> null
-       id                     = "dist/js/605.aa684f31.js.map" -> null
-       key                    = "dist/js/605.aa684f31.js.map" -> null
-       metadata               = {} -> null
-       server_side_encryption = "AES256" -> null
-       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/605.aa684f31.js.map" -> null
-       source_hash            = "c758bea9d097d4d40418afa74f514643" -> null
-       storage_class          = "STANDARD" -> null
-       tags                   = {} -> null
-       tags_all               = {
-           "env"        = "staging"
-           "management" = "terraform"
-           "owner"      = "grants"
-           "repo"       = "usdr-gost"
-           "service"    = "gost"
-           "usage"      = "workload"
        } -> null
-       version_id             = "wnvCabBiVHX.4pDbxqwn_dNZ.L7eSD5H" -> null
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/605.e9d03ed7.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "e304b2b9b7b9e2a9c8e77273f28aa8ea"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/605.e9d03ed7.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/605.e9d03ed7.js"
+       source_hash            = "e304b2b9b7b9e2a9c8e77273f28aa8ea"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/605.e9d03ed7.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "203cc2de7da002293c642cc6dc07b264"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/605.e9d03ed7.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/605.e9d03ed7.js.map"
+       source_hash            = "203cc2de7da002293c642cc6dc07b264"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/641.0fcafc97.js"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "text/javascript"
+       etag                   = "c8ea7117af57957dafe4b3ddcb4e4812"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/641.0fcafc97.js"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/641.0fcafc97.js"
+       source_hash            = "c8ea7117af57957dafe4b3ddcb4e4812"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/641.0fcafc97.js.map"] will be created
+   resource "aws_s3_object" "origin_dist_artifact" {
+       acl                    = "private"
+       bucket                 = "gost-staging-origin-357150818708-us-west-2-website"
+       bucket_key_enabled     = (known after apply)
+       content_type           = "application/json"
+       etag                   = "68fdc1445813ca04e4b54a9789e55c7f"
+       force_destroy          = false
+       id                     = (known after apply)
+       key                    = "dist/js/641.0fcafc97.js.map"
+       kms_key_id             = (known after apply)
+       server_side_encryption = "AES256"
+       source                 = "/home/runner/work/usdr-gost/usdr-gost/packages/client/dist/js/641.0fcafc97.js.map"
+       source_hash            = "68fdc1445813ca04e4b54a9789e55c7f"
+       storage_class          = (known after apply)
+       tags_all               = {
+           "env"        = "staging"
+           "management" = "terraform"
+           "owner"      = "grants"
+           "repo"       = "usdr-gost"
+           "service"    = "gost"
+           "usage"      = "workload"
        }
+       version_id             = (known after apply)
    }

  # module.website.aws_s3_object.origin_dist_artifact["js/641.d261cd52.js"] will be destroyed
  # (because key ["js/641.d261cd52.js"] is not in for_each map)
-   resource "aws_s3_object" "origin_dist_artifact" {
-       acl                    = "private" -> null
-       bucket                 = "gost-staging-origin-357150818708-us-west-2-website" -> null
-       bucket_key_e...*[Comment body truncated]*

terraform/main.tf Outdated Show resolved Hide resolved
terraform/main.tf Outdated Show resolved Hide resolved
@TylerHendrickson TylerHendrickson added the Grant Finder Issues related to the Grant Finder label Apr 2, 2024
@jeffsmohan jeffsmohan force-pushed the jmo-digest-emails-cron branch 2 times, most recently from f67ed05 to 7dcb60f Compare April 3, 2024 18:16
@jeffsmohan jeffsmohan changed the title Rough draft: scheduled task for send grant digest emails Scheduled task for send grant digest emails Apr 3, 2024
@jeffsmohan jeffsmohan force-pushed the jmo-digest-emails-cron branch from 7dcb60f to 9295541 Compare April 3, 2024 18:28
api_enable_new_team_terminology = true
api_enable_my_profile = true
api_enable_saved_search_grants_digest = true
api_enable_grant_digest_scheduled_task = false
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written, this PR uses this variable simultaneously to disable running the ECS scheduled task (enabled = var.api_enabled && var.api_enable_grant_digest_scheduled_task) and to short-circuit the script itself (if (process.env.ENABLE_GRANT_DIGEST_SCHEDULED_TASK !== 'true') { return; }). Does this feel redundant? Or helpful on the off chance the script gets triggered via some other means?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if the configuration is ultimately sourced from one place, I think that being able to have a check at the infrastructure level as well as at the runtime level is a useful separation of concerns, so this feels right to me.

api_enable_new_team_terminology = true
api_enable_my_profile = true
api_enable_saved_search_grants_digest = true
api_enable_grant_digest_scheduled_task = false
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this to be flipped to true in staging so we can test the functionality as soon as it lands?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please!

@jeffsmohan jeffsmohan marked this pull request as ready for review April 3, 2024 18:34
@jeffsmohan jeffsmohan force-pushed the jmo-digest-emails-cron branch 3 times, most recently from e6a0009 to 597fff9 Compare April 3, 2024 19:19
I believe this is necessary for it to have access to the
aws_ecs_task_definition resource without having to redefine that at the
terraform root level
@jeffsmohan jeffsmohan force-pushed the jmo-digest-emails-cron branch from 597fff9 to 676a0ed Compare April 3, 2024 19:27
Comment on lines 128 to 137
module "grant_digest_scheduled_task_security_group" {
source = "cloudposse/security-group/aws"
version = "2.2.0"

namespace = var.namespace
vpc_id = data.aws_ssm_parameter.vpc_id.value
attributes = ["grant_digest_scheduled_task"]
allow_all_egress = true
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It occurs to me that, since the grant_digest_scheduled_task module defined in terraform/modules/gost_api/grant_digest.tf is configured with all the same security groups that are passed in for any other task (specifically the main API workers) controlled by terraform/modules/gost_api, this security group is redundant.

To be super verbose: the terraform/modules/gost_api module source uses all provided values in var.security_group_ids when placing tasks in various security groups. More to the point, it passes this same list directly to its module "grants_digest_scheduled_task" resource. Since this list already contains a security group common to our Postgres cluster*, we don't need to provide another. The only reason this new security group would be necessary is if terraform/modules/gost_api declared a new input variable like var.grants_digest_scheduled_task_security_groups and only used those values when configuring networking for that task.

I should have caught this during our review yesterday, but I was (mistakenly) thinking that the module "grant_digest_scheduled_task" resource would be defined in the main project (terraform/ directory) rather than as a sub-resource of module "gost_api".

*Feel free to ignore everything below, but looking at the current security group configuration, it appears we somehow mismatched the api_to_postgres_security_group and consume_grants_to_postgres_security_group usages. The configuration should be:

  • module.api_to_postgres_security_group.id passed to:
    • module "gost_api" via security_group_ids input variable array
    • module "postgres" via ingress_security_groups input variable array
  • module.consume_grants_to_postgres_security_group.id passed to the security_group_ids input variable arrays for:
    • module "consume_grants" via security_group_ids input variable array
    • module "postgres" via ingress_security_groups input variable array

This mismatch isn't the most major problem in the world – both security groups are configured identically, so this is ultimately just a naming convention, and they could even be consolidated down to a single security group. Just mentioning here because I noticed while reviewing.

TL;DR You can safely remove the module "grant_digest_scheduled_task_security_group" resource and its usages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I was borrowing this idiom from things like arpa_treasury_report_security_group, but your assessment makes sense, and it does seem like consolidating security groups to a clear set of logical groupings, rather than "one per process", makes more sense to me.

I should have caught this during our review yesterday, but I was (mistakenly) thinking that the module "grant_digest_scheduled_task" resource would be defined in the main project (terraform/ directory) rather than as a sub-resource of module "gost_api".

Fwiw, it was located in terraform/main.tf originally, but I moved it under the gost_api module to reuse the aws_ecs_task_definition instead of having to redefine it.

Anyway, I'll remove the new security group!

Comment on lines +3 to +6
data "aws_ecs_cluster" "default" {
count = var.enabled ? 1 : 0
cluster_name = var.ecs_cluster_name
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

api_enable_new_team_terminology = true
api_enable_my_profile = true
api_enable_saved_search_grants_digest = true
api_enable_grant_digest_scheduled_task = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if the configuration is ultimately sourced from one place, I think that being able to have a check at the infrastructure level as well as at the runtime level is a useful separation of concerns, so this feels right to me.

api_enable_new_team_terminology = true
api_enable_my_profile = true
api_enable_saved_search_grants_digest = true
api_enable_grant_digest_scheduled_task = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please!

@jeffsmohan
Copy link
Contributor Author

@TylerHendrickson comments addressed, back to you!

Copy link
Member

@TylerHendrickson TylerHendrickson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Edit: Looks like there was a formatting issue after this change; pushed up results of terraform fmt.

Copy link
Member

@TylerHendrickson TylerHendrickson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeffsmohan New requested change based on the current CI failure.

source = "../scheduled_ecs_task"
enabled = var.enabled && var.enable_grant_digest_scheduled_task

name_prefix = "${var.namespace}-grant-digest-scheduled-task"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is annoying, but this error in the failing terraform plan CI job is due to this name_prefix value being too long for certain AWS resources' max character restrictions – the value for the Staging environment, gost-staging-grant-digest-scheduled-task, is 40 characters, and the max length for an IAM role prefix is 38 characters ☹️

The fix is fortunately easy, albeit not quite as readable as the current solution:

Suggested change
name_prefix = "${var.namespace}-grant-digest-scheduled-task"
name_prefix = "${var.namespace}-grant-digest-task"

Other preferences for shortening this value (gost-staging-grant-digest-sched-task is 37 characters, for example) are also acceptable.

@jeffsmohan
Copy link
Contributor Author

@TylerHendrickson fixed!

@TylerHendrickson TylerHendrickson enabled auto-merge (squash) April 4, 2024 18:01
@TylerHendrickson TylerHendrickson merged commit 49fc242 into main Apr 4, 2024
19 checks passed
@TylerHendrickson TylerHendrickson deleted the jmo-digest-emails-cron branch April 4, 2024 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Grant Finder Issues related to the Grant Finder Infra Issues related to the infrastructure underlying all the tools. javascript Pull requests that update Javascript code terraform Pull requests that update Terraform code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants