Skip to content

Conversation

@ohrite
Copy link
Contributor

@ohrite ohrite commented Nov 21, 2025

Description

This PR rewrites the NTD Excel processing operators and Gusty DAG definition to include test coverage for operators and hooks

Resolves #4380

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

How has this been tested?

pytest

Post-merge follow-ups

  • No action required
  • Actions required (specified below)

Monitor staging execution

@ohrite ohrite force-pushed the mov/4380-ntd-xlsx-download branch from 8b3b8a9 to bcf5287 Compare November 21, 2025 17:25
@github-actions
Copy link

github-actions bot commented Nov 21, 2025

Terraform plan in iac/cal-itp-data-infra-staging/composer/us

No changes. Your infrastructure matches the configuration.
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

📝 Plan generated in Plan Terraform for Warehouse and DAG changes #1169

@github-actions
Copy link

github-actions bot commented Nov 21, 2025

Terraform plan in iac/cal-itp-data-infra/airflow/us

Plan: 5 to add, 0 to change, 0 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+   create

Terraform will perform the following actions:

  # google_storage_bucket_object.calitp-composer["dags/download_and_parse_ntd_xlsx.py"] will be created
+   resource "google_storage_bucket_object" "calitp-composer" {
+       bucket         = "calitp-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "dags/download_and_parse_ntd_xlsx.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/dags/download_and_parse_ntd_xlsx.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-composer["plugins/hooks/ntd_xlsx_hook.py"] will be created
+   resource "google_storage_bucket_object" "calitp-composer" {
+       bucket         = "calitp-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/hooks/ntd_xlsx_hook.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/hooks/ntd_xlsx_hook.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-composer["plugins/operators/ntd_xlsx_list_tabs_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-composer" {
+       bucket         = "calitp-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_list_tabs_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_list_tabs_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-composer["plugins/operators/ntd_xlsx_to_gcs_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-composer" {
+       bucket         = "calitp-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-composer["plugins/operators/ntd_xlsx_to_jsonl_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-composer" {
+       bucket         = "calitp-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_to_jsonl_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_to_jsonl_operator.py"
+       storage_class  = (known after apply)
    }

Plan: 5 to add, 0 to change, 0 to destroy.

📝 Plan generated in Plan Terraform for Warehouse and DAG changes #1169

@github-actions
Copy link

github-actions bot commented Nov 21, 2025

Terraform plan in iac/cal-itp-data-infra-staging/airflow/us

Plan: 5 to add, 2 to change, 0 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+   create
!~  update in-place

Terraform will perform the following actions:

  # google_storage_bucket_object.calitp-staging-composer["dags/download_and_parse_ntd_xlsx.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "dags/download_and_parse_ntd_xlsx.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/dags/download_and_parse_ntd_xlsx.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/hooks/ntd_xlsx_hook.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/hooks/ntd_xlsx_hook.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/hooks/ntd_xlsx_hook.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/ntd_xlsx_list_tabs_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_list_tabs_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_list_tabs_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/ntd_xlsx_to_gcs_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/ntd_xlsx_to_jsonl_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_to_jsonl_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_to_jsonl_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer-catalog will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer-catalog" {
!~      content             = (sensitive value)
!~      crc32c              = "KFEMgw==" -> (known after apply)
!~      detect_md5hash      = "FcddRn1vcGiT6Fc+seoihQ==" -> "different hash"
!~      generation          = 1765318154134732 -> (known after apply)
        id                  = "calitp-staging-composer-data/warehouse/target/catalog.json"
!~      md5hash             = "FcddRn1vcGiT6Fc+seoihQ==" -> (known after apply)
        name                = "data/warehouse/target/catalog.json"
#        (16 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer-manifest will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer-manifest" {
!~      content             = (sensitive value)
!~      crc32c              = "4BO/Pw==" -> (known after apply)
!~      detect_md5hash      = "DVr5N9SKcJwP6GHtb+dYEg==" -> "different hash"
!~      generation          = 1765318155436013 -> (known after apply)
        id                  = "calitp-staging-composer-data/warehouse/target/manifest.json"
!~      md5hash             = "DVr5N9SKcJwP6GHtb+dYEg==" -> (known after apply)
        name                = "data/warehouse/target/manifest.json"
#        (16 unchanged attributes hidden)
    }

Plan: 5 to add, 2 to change, 0 to destroy.

📝 Plan generated in Plan Terraform for Warehouse and DAG changes #1169

@github-actions
Copy link

Terraform plan in iac/cal-itp-data-infra-staging/airflow/us

Plan: 2 to add, 17 to change, 3 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+   create
!~  update in-place
-   destroy

Terraform will perform the following actions:

  # google_storage_bucket_object.calitp-staging-composer["dags/airtable_loader_v2/generate_gtfs_download_configs.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "MijWlA==" -> (known after apply)
!~      detect_md5hash      = "s632w01yc8uo408y4VdAyw==" -> "different hash"
!~      generation          = 1763690417635115 -> (known after apply)
        id                  = "calitp-staging-composer-dags/airtable_loader_v2/generate_gtfs_download_configs.py"
!~      md5hash             = "s632w01yc8uo408y4VdAyw==" -> (known after apply)
        name                = "dags/airtable_loader_v2/generate_gtfs_download_configs.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["dags/download_gtfs_schedule_v2/download_schedule_feeds.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "8qLecA==" -> (known after apply)
!~      detect_md5hash      = "iGapm0xJ3U0wowUUkId1eQ==" -> "different hash"
!~      generation          = 1763690417218909 -> (known after apply)
        id                  = "calitp-staging-composer-dags/download_gtfs_schedule_v2/download_schedule_feeds.py"
!~      md5hash             = "iGapm0xJ3U0wowUUkId1eQ==" -> (known after apply)
        name                = "dags/download_gtfs_schedule_v2/download_schedule_feeds.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["dags/sync_ntd_data_xlsx/scrape_ntd_xlsx_urls.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "g2TBuw==" -> (known after apply)
!~      detect_md5hash      = "PSes9rK7j0FP6JcNRQhPLg==" -> "different hash"
!~      generation          = 1763690417804807 -> (known after apply)
        id                  = "calitp-staging-composer-dags/sync_ntd_data_xlsx/scrape_ntd_xlsx_urls.py"
!~      md5hash             = "PSes9rK7j0FP6JcNRQhPLg==" -> (known after apply)
        name                = "dags/sync_ntd_data_xlsx/scrape_ntd_xlsx_urls.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/calitp_data_infra/__init__.py"] will be destroyed
  # (because key ["plugins/calitp_data_infra/__init__.py"] is not in for_each map)
-   resource "google_storage_bucket_object" "calitp-staging-composer" {
-       bucket              = "calitp-staging-composer" -> null
-       content_type        = "text/plain; charset=utf-8" -> null
-       crc32c              = "AAAAAA==" -> null
-       detect_md5hash      = "1B2M2Y8AsgTpgAmY7PhCfg==" -> null
-       event_based_hold    = false -> null
-       generation          = 1763690417199832 -> null
-       id                  = "calitp-staging-composer-plugins/calitp_data_infra/__init__.py" -> null
-       md5hash             = "1B2M2Y8AsgTpgAmY7PhCfg==" -> null
-       md5hexhash          = "d41d8cd98f00b204e9800998ecf8427e" -> null
-       media_link          = "https://storage.googleapis.com/download/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2F__init__.py?generation=1763690417199832&alt=media" -> null
-       metadata            = {} -> null
-       name                = "plugins/calitp_data_infra/__init__.py" -> null
-       output_name         = "plugins/calitp_data_infra/__init__.py" -> null
-       self_link           = "https://www.googleapis.com/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2F__init__.py" -> null
-       source              = "../../../../airflow/plugins/calitp_data_infra/__init__.py" -> null
-       storage_class       = "STANDARD" -> null
-       temporary_hold      = false -> null
#        (6 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/calitp_data_infra/auth.py"] will be destroyed
  # (because key ["plugins/calitp_data_infra/auth.py"] is not in for_each map)
-   resource "google_storage_bucket_object" "calitp-staging-composer" {
-       bucket              = "calitp-staging-composer" -> null
-       content_type        = "text/plain; charset=utf-8" -> null
-       crc32c              = "6lsUtA==" -> null
-       detect_md5hash      = "+/KTbwc3sd3B4wBkY+HoUw==" -> null
-       event_based_hold    = false -> null
-       generation          = 1763690417207979 -> null
-       id                  = "calitp-staging-composer-plugins/calitp_data_infra/auth.py" -> null
-       md5hash             = "+/KTbwc3sd3B4wBkY+HoUw==" -> null
-       md5hexhash          = "fbf2936f0737b1ddc1e3006463e1e853" -> null
-       media_link          = "https://storage.googleapis.com/download/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2Fauth.py?generation=1763690417207979&alt=media" -> null
-       metadata            = {} -> null
-       name                = "plugins/calitp_data_infra/auth.py" -> null
-       output_name         = "plugins/calitp_data_infra/auth.py" -> null
-       self_link           = "https://www.googleapis.com/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2Fauth.py" -> null
-       source              = "../../../../airflow/plugins/calitp_data_infra/auth.py" -> null
-       storage_class       = "STANDARD" -> null
-       temporary_hold      = false -> null
#        (6 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/calitp_data_infra/storage.py"] will be destroyed
  # (because key ["plugins/calitp_data_infra/storage.py"] is not in for_each map)
-   resource "google_storage_bucket_object" "calitp-staging-composer" {
-       bucket              = "calitp-staging-composer" -> null
-       content_type        = "text/plain; charset=utf-8" -> null
-       crc32c              = "b87VYA==" -> null
-       detect_md5hash      = "sq1Q+wmsL8o0RKJLFUFC7g==" -> null
-       event_based_hold    = false -> null
-       generation          = 1763690417395966 -> null
-       id                  = "calitp-staging-composer-plugins/calitp_data_infra/storage.py" -> null
-       md5hash             = "sq1Q+wmsL8o0RKJLFUFC7g==" -> null
-       md5hexhash          = "b2ad50fb09ac2fca3444a24b154142ee" -> null
-       media_link          = "https://storage.googleapis.com/download/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2Fstorage.py?generation=1763690417395966&alt=media" -> null
-       metadata            = {} -> null
-       name                = "plugins/calitp_data_infra/storage.py" -> null
-       output_name         = "plugins/calitp_data_infra/storage.py" -> null
-       self_link           = "https://www.googleapis.com/storage/v1/b/calitp-staging-composer/o/plugins%2Fcalitp_data_infra%2Fstorage.py" -> null
-       source              = "../../../../airflow/plugins/calitp_data_infra/storage.py" -> null
-       storage_class       = "STANDARD" -> null
-       temporary_hold      = false -> null
#        (6 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/hooks/kuba_hook.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "pIf6jA==" -> (known after apply)
!~      detect_md5hash      = "M9n0Cr7dL9+4asfxnMHgjQ==" -> "different hash"
!~      generation          = 1763690418428084 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/hooks/kuba_hook.py"
!~      md5hash             = "M9n0Cr7dL9+4asfxnMHgjQ==" -> (known after apply)
        name                = "plugins/hooks/kuba_hook.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/hooks/ntd_xlsx_hook.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/hooks/ntd_xlsx_hook.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/hooks/ntd_xlsx_hook.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/hooks/soda_hook.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "Wxj+aQ==" -> (known after apply)
!~      detect_md5hash      = "CDAoj9pONq2nsD5BT43vEg==" -> "different hash"
!~      generation          = 1763690418284709 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/hooks/soda_hook.py"
!~      md5hash             = "CDAoj9pONq2nsD5BT43vEg==" -> (known after apply)
        name                = "plugins/hooks/soda_hook.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/hooks/transitland_hook.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "xolZ/w==" -> (known after apply)
!~      detect_md5hash      = "lMSV7OyTWTBE5ar8Ush1oA==" -> "different hash"
!~      generation          = 1763690417210931 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/hooks/transitland_hook.py"
!~      md5hash             = "lMSV7OyTWTBE5ar8Ush1oA==" -> (known after apply)
        name                = "plugins/hooks/transitland_hook.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/aggregator_to_gcs_operator.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "h26Utg==" -> (known after apply)
!~      detect_md5hash      = "+2mzXgNPW36mWf5Z3ZZBag==" -> "different hash"
!~      generation          = 1763690417144134 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/aggregator_to_gcs_operator.py"
!~      md5hash             = "+2mzXgNPW36mWf5Z3ZZBag==" -> (known after apply)
        name                = "plugins/operators/aggregator_to_gcs_operator.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/blackcat_to_gcs_operator.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "s7BJ7Q==" -> (known after apply)
!~      detect_md5hash      = "husvfrVLOwWESpUczaAT3w==" -> "different hash"
!~      generation          = 1763690417861255 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/blackcat_to_gcs_operator.py"
!~      md5hash             = "husvfrVLOwWESpUczaAT3w==" -> (known after apply)
        name                = "plugins/operators/blackcat_to_gcs_operator.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/dbt_manifest_to_dictionary_operator.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "4MyK1Q==" -> (known after apply)
!~      detect_md5hash      = "FIHwYcjOm5NPB+nPb7enyg==" -> "different hash"
!~      generation          = 1763690416913428 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/dbt_manifest_to_dictionary_operator.py"
!~      md5hash             = "FIHwYcjOm5NPB+nPb7enyg==" -> (known after apply)
        name                = "plugins/operators/dbt_manifest_to_dictionary_operator.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/dbt_manifest_to_metadata_operator.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "UDX9og==" -> (known after apply)
!~      detect_md5hash      = "F4n9FAx9ExF1Zl3J7NaMWQ==" -> "different hash"
!~      generation          = 1763690417995295 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/dbt_manifest_to_metadata_operator.py"
!~      md5hash             = "F4n9FAx9ExF1Zl3J7NaMWQ==" -> (known after apply)
        name                = "plugins/operators/dbt_manifest_to_metadata_operator.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/gtfs_csv_to_jsonl_hourly.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "pCzW9g==" -> (known after apply)
!~      detect_md5hash      = "n34Iv1u6y/wZeOnqO2WDEA==" -> "different hash"
!~      generation          = 1763690417647780 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/gtfs_csv_to_jsonl_hourly.py"
!~      md5hash             = "n34Iv1u6y/wZeOnqO2WDEA==" -> (known after apply)
        name                = "plugins/operators/gtfs_csv_to_jsonl_hourly.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/littlepay_raw_sync_feed_v3.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "TDDjLg==" -> (known after apply)
!~      detect_md5hash      = "zXyVjenO8Z0Xcx4u85EVYQ==" -> "different hash"
!~      generation          = 1763690417211071 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/littlepay_raw_sync_feed_v3.py"
!~      md5hash             = "zXyVjenO8Z0Xcx4u85EVYQ==" -> (known after apply)
        name                = "plugins/operators/littlepay_raw_sync_feed_v3.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/ntd_xlsx_to_gcs_operator.py"] will be created
+   resource "google_storage_bucket_object" "calitp-staging-composer" {
+       bucket         = "calitp-staging-composer"
+       content        = (sensitive value)
+       content_type   = (known after apply)
+       crc32c         = (known after apply)
+       detect_md5hash = "different hash"
+       generation     = (known after apply)
+       id             = (known after apply)
+       kms_key_name   = (known after apply)
+       md5hash        = (known after apply)
+       md5hexhash     = (known after apply)
+       media_link     = (known after apply)
+       name           = "plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       output_name    = (known after apply)
+       self_link      = (known after apply)
+       source         = "../../../../airflow/plugins/operators/ntd_xlsx_to_gcs_operator.py"
+       storage_class  = (known after apply)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/pod_operator.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "H81Llg==" -> (known after apply)
!~      detect_md5hash      = "6vO0LHE3p5d/cOQ71Ghv8g==" -> "different hash"
!~      generation          = 1763690417200759 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/pod_operator.py"
!~      md5hash             = "6vO0LHE3p5d/cOQ71Ghv8g==" -> (known after apply)
        name                = "plugins/operators/pod_operator.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/scrape_ntd_xlsx.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "800p7w==" -> (known after apply)
!~      detect_md5hash      = "+sUY5347tlkwmkjx/59Ytg==" -> "different hash"
!~      generation          = 1763690417819438 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/scrape_ntd_xlsx.py"
!~      md5hash             = "+sUY5347tlkwmkjx/59Ytg==" -> (known after apply)
        name                = "plugins/operators/scrape_ntd_xlsx.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/operators/scrape_state_geoportal.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "HSTs0g==" -> (known after apply)
!~      detect_md5hash      = "kroDAzyyod9g32UxYWccew==" -> "different hash"
!~      generation          = 1763690418239800 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/operators/scrape_state_geoportal.py"
!~      md5hash             = "kroDAzyyod9g32UxYWccew==" -> (known after apply)
        name                = "plugins/operators/scrape_state_geoportal.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/scripts/gtfs_rt_parser.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "XjBzGA==" -> (known after apply)
!~      detect_md5hash      = "BfvE2ctBSfWnSYBpIv2hOg==" -> "different hash"
!~      generation          = 1763690417837883 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/scripts/gtfs_rt_parser.py"
!~      md5hash             = "BfvE2ctBSfWnSYBpIv2hOg==" -> (known after apply)
        name                = "plugins/scripts/gtfs_rt_parser.py"
#        (17 unchanged attributes hidden)
    }

  # google_storage_bucket_object.calitp-staging-composer["plugins/utils.py"] will be updated in-place
!~  resource "google_storage_bucket_object" "calitp-staging-composer" {
!~      crc32c              = "2wseZw==" -> (known after apply)
!~      detect_md5hash      = "L7u5luMr8c8OXJVHR7nzEg==" -> "different hash"
!~      generation          = 1763690417826500 -> (known after apply)
        id                  = "calitp-staging-composer-plugins/utils.py"
!~      md5hash             = "L7u5luMr8c8OXJVHR7nzEg==" -> (known after apply)
        name                = "plugins/utils.py"
#        (17 unchanged attributes hidden)
    }

Plan: 2 to add, 17 to change, 3 to destroy.

📝 Plan generated in Plan Terraform for Warehouse and DAG changes #1070

@ohrite ohrite force-pushed the mov/4380-ntd-xlsx-download branch 4 times, most recently from 70b7cbf to 7810c47 Compare November 25, 2025 22:26
@github-actions
Copy link

github-actions bot commented Nov 25, 2025

Terraform plan in iac/cal-itp-data-infra/composer/us

No changes. Your infrastructure matches the configuration.
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

📝 Plan generated in Plan Terraform for Warehouse and DAG changes #1169

@ohrite ohrite force-pushed the mov/4380-ntd-xlsx-download branch 5 times, most recently from 2d9db09 to 599dedb Compare December 3, 2025 04:24
@ohrite ohrite marked this pull request as ready for review December 3, 2025 21:09
@ohrite ohrite force-pushed the mov/4380-ntd-xlsx-download branch from 599dedb to 4d9e1d9 Compare December 10, 2025 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Developer sees that there is unit test coverage for NTD Excel download

3 participants