Skip to content

release: infra dev to main - #69

Merged
jm-rivera merged 8 commits into
mainfrom
dev
Oct 23, 2026
Merged

jm-rivera merged 8 commits into
mainfrom
dev

Conversation

@jm-rivera

Copy link
Copy Markdown
Contributor

Releases infra dev to main: the prod telemetry stack (#59), group and person addresses read from Secret Manager (#66), and the dcp serving account's grant on the Gemini key secret (#60).

Testing: each change applied in dev from these commits, and the dev plans masked every principal address. plan-prod.yml plans prod on this PR with main's workflows, which mask principal addresses since the last release.

DCP 1.1.6 removes the serving service account's project-wide
secretmanager.secretAccessor role. null_resource.search_api_gemini_key
attaches the ${namespace}-gemini-api-key secret to the datacommons
service as GEMINI_API_KEY, and a revision whose account cannot read the
secret fails to start, so the script's rollout and the apply would
fail. A per-secret grant on data.google_secret_manager_secret.search_api_gemini
keeps the access under both module versions, and the key script waits
for it.

The key serves the DFO prototype app's /prototype/api/similarity and
/prototype/api/skill-compare routes; /api/search goes to dfo-apis.
The comments and READMEs say so.
infra/stacks/dcp/main.tf, variables.tf and outputs.tf are upstream's
1.1.6 root files with the module ref pinned to v1.1.6. dcp_version
defaults to 1.1.6, which picks the 1.1.6 ingestion images, the
ingestion-1.1.6 Dataflow template and the new rollback template.
Preprocessing runs as a Cloud Batch job with cpu and memory in milliCPU
and MiB, so batch.googleapis.com joins the enabled APIs. The
ingestion_prep_job_name output goes, since the Cloud Run preprocessing
job no longer exists.

The justfile pins CLI 1.1.6. seed-db is removed, init-db drops
--init-only, and init-db and migrate-db run under the caller's
application default credentials, which need roles/spanner.databaseAdmin
and roles/spanner.databaseUser. docs/development.md and the dfo-dev
dcp README state the same.
Preprocessing runs as a Cloud Batch job, so ingestion operators get
roles/batch.jobsViewer beside roles/run.viewer, which still covers the
postprocessing job's executions. The 1.1.6 module has no VPC Access
connector and no google_compute_network data source with DFO's
settings, so the applier drops roles/vpcaccess.admin and
roles/compute.networkViewer.

The storage_artifacts_bucket_enable_versioning setting goes from both
environments: the module's bucket has count 0 here, so it set nothing.
dcp-tools 1.1.0 reads the ingestion workflow's definition before it
starts an execution and refuses a workflow older than DCP 1.1.6. It
runs as the ingestion workflow service account when callers impersonate
it, and the module grants that account only roles/workflows.invoker,
which lacks workflows.workflows.get. The account gets
roles/workflows.viewer.
…16-prep

feat(dcp): grant the serving account the Gemini key secret
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Terraform Plan — telemetry

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

Init Validate Plan
pass pass pass
Show plan
module.principals.data.google_secret_manager_secret_version.this: Reading...
data.google_project.this: Reading...
data.google_project.this: Read complete after 0s [id=projects/prod-fin-observatory]
module.principals.data.google_secret_manager_secret_version.this: Read complete after 0s [id=projects/533754688761/secrets/dfo-prod-telemetry-principals/versions/1]

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_bigquery_data_transfer_config.logs_daily will be created
  + resource "google_bigquery_data_transfer_config" "logs_daily" {
      + data_source_id       = "scheduled_query"
      + deletion_policy      = "DELETE"
      + display_name         = "dfo-prod-logs-daily"
      + id                   = (known after apply)
      + location             = "EU"
      + name                 = (known after apply)
      + params               = {
          + "query" = <<-EOT
                -- The logs_daily scheduled query, a Terraform template (logs_daily.tf). It
                -- reads prod-fin-observatory.dfo_logs._AllLogs, the linked dataset's view of every routed Cloud Run entry,
                -- and writes four tables in prod-fin-observatory.logs_daily, creating them on the first run.
                --
                -- The source's oldest day is partial, since the sink started or retention
                -- cut entries part way through it, so the oldest whole day is the one after.
                -- requests_daily, routes_daily and errors_daily replace the days from
                -- requests_daily's latest loaded day minus one through today, and from the
                -- oldest whole day when requests_daily is empty. The start never falls
                -- before the oldest whole day, so every day a run deletes is a day it
                -- reloads in full, even after an outage longer than the source's retention.
                -- errors_daily shares requests_daily's start, so a stretch with no warnings
                -- cannot widen its window. A source with no entries loads and deletes
                -- nothing, since the start is then NULL.
                --
                -- deploys gains a row for each revision it has not seen, timed at the
                -- revision's first request across the whole source, and never changes a row
                -- once written. before_source is true, as of the run that records the
                -- revision, when no other revision of its service served a request earlier
                -- in the source. A revision with an earlier sibling was deployed after the
                -- source began. One without was serving when the source began, or is the
                -- first after a service-wide silence longer than retention, or the first of
                -- a new service. Its first request is not a known deploy, so deploy markers
                -- read only rows where before_source is false. Recording it anyway keeps it
                -- out of later runs, which would otherwise time it at whatever request
                -- survives retention and mark a deploy weeks late.
                -- Days are UTC.
                
                DECLARE source_first_day, load_from DATE;
                
                CREATE TABLE IF NOT EXISTS `prod-fin-observatory.logs_daily.requests_daily` (
                  day DATE NOT NULL,
                  service STRING NOT NULL,
                  requests INT64 NOT NULL,
                  status_4xx INT64 NOT NULL,
                  status_5xx INT64 NOT NULL,
                  latency_p50_ms FLOAT64,
                  latency_p95_ms FLOAT64,
                  latency_p99_ms FLOAT64
                )
                PARTITION BY day
                OPTIONS (description = 'Cloud Run requests per UTC day and service, with status counts and approximate latency quantiles.');
                
                CREATE TABLE IF NOT EXISTS `prod-fin-observatory.logs_daily.routes_daily` (
                  day DATE NOT NULL,
                  service STRING NOT NULL,
                  method STRING,
                  route STRING,
                  requests INT64 NOT NULL,
                  status_4xx INT64 NOT NULL,
                  status_5xx INT64 NOT NULL,
                  latency_p50_ms FLOAT64,
                  latency_p95_ms FLOAT64,
                  latency_p99_ms FLOAT64
                )
                PARTITION BY day
                CLUSTER BY service
                OPTIONS (description = 'Cloud Run requests per UTC day, service, method and route, where route is prod-fin-observatory.logs_daily.normalise_route(requestUrl).');
                
                CREATE TABLE IF NOT EXISTS `prod-fin-observatory.logs_daily.errors_daily` (
                  day DATE NOT NULL,
                  resource_type STRING NOT NULL,
                  service STRING NOT NULL,
                  logger STRING,
                  severity STRING NOT NULL,
                  entries INT64 NOT NULL
                )
                PARTITION BY day
                OPTIONS (description = 'Cloud Run service and job stdout and stderr entries at WARNING or above, per UTC day, service or job, logger and severity. No message text.');
                
                CREATE TABLE IF NOT EXISTS `prod-fin-observatory.logs_daily.deploys` (
                  service STRING NOT NULL,
                  revision STRING NOT NULL,
                  first_request TIMESTAMP NOT NULL,
                  before_source BOOL NOT NULL
                )
                OPTIONS (description = 'Each Cloud Run revision that served a request, with the time of its first request. before_source is true for a revision already serving when the logs source began, whose first_request is not its deploy.');
                
                SET source_first_day = (SELECT DATE(MIN(timestamp)) FROM `prod-fin-observatory.dfo_logs._AllLogs`);
                SET load_from = (
                  SELECT GREATEST(IFNULL(MAX(day) - 1, source_first_day + 1), source_first_day + 1)
                  FROM `prod-fin-observatory.logs_daily.requests_daily`
                );
                
                CREATE TEMP TABLE requests AS
                SELECT
                  DATE(timestamp) AS day,
                  JSON_VALUE(resource.labels.service_name) AS service,
                  http_request.request_method AS method,
                  `prod-fin-observatory.logs_daily.normalise_route`(http_request.request_url) AS route,
                  http_request.status AS status,
                  -- latency is a STRUCT of INT64 seconds and nanos, and an entry may omit a
                  -- zero component.
                  IF(
                    http_request.latency IS NULL,
                    NULL,
                    IFNULL(http_request.latency.seconds, 0) * 1000 + IFNULL(http_request.latency.nanos, 0) / 1e6
                  ) AS latency_ms
                FROM `prod-fin-observatory.dfo_logs._AllLogs`
                WHERE timestamp >= TIMESTAMP(load_from)
                  AND resource.type = 'cloud_run_revision'
                  AND log_id = 'run.googleapis.com/requests';
                
                BEGIN TRANSACTION;
                
                DELETE FROM `prod-fin-observatory.logs_daily.requests_daily` WHERE day >= load_from;
                INSERT INTO `prod-fin-observatory.logs_daily.requests_daily`
                SELECT
                  day,
                  service,
                  COUNT(*),
                  COUNTIF(status BETWEEN 400 AND 499),
                  COUNTIF(status BETWEEN 500 AND 599),
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(50)],
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(95)],
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(99)]
                FROM requests
                WHERE day >= load_from
                GROUP BY day, service;
                
                DELETE FROM `prod-fin-observatory.logs_daily.routes_daily` WHERE day >= load_from;
                INSERT INTO `prod-fin-observatory.logs_daily.routes_daily`
                SELECT
                  day,
                  service,
                  method,
                  route,
                  COUNT(*),
                  COUNTIF(status BETWEEN 400 AND 499),
                  COUNTIF(status BETWEEN 500 AND 599),
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(50)],
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(95)],
                  APPROX_QUANTILES(latency_ms, 100)[SAFE_OFFSET(99)]
                FROM requests
                WHERE day >= load_from
                GROUP BY day, service, method, route;
                
                DELETE FROM `prod-fin-observatory.logs_daily.errors_daily` WHERE day >= load_from;
                INSERT INTO `prod-fin-observatory.logs_daily.errors_daily`
                SELECT
                  DATE(timestamp),
                  resource.type,
                  COALESCE(JSON_VALUE(resource.labels.service_name), JSON_VALUE(resource.labels.job_name)),
                  JSON_VALUE(json_payload.logger),
                  severity,
                  COUNT(*)
                FROM `prod-fin-observatory.dfo_logs._AllLogs`
                WHERE timestamp >= TIMESTAMP(load_from)
                  AND log_id IN ('run.googleapis.com/stdout', 'run.googleapis.com/stderr')
                  AND severity IN ('WARNING', 'ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY')
                GROUP BY 1, 2, 3, 4, 5;
                
                INSERT INTO `prod-fin-observatory.logs_daily.deploys`
                SELECT service, revision, first_request, before_source
                FROM (
                  -- Every revision in the source, recorded or not, so the earliest sibling
                  -- can be one deploys already holds.
                  SELECT
                    service,
                    revision,
                    first_request,
                    first_request = MIN(first_request) OVER (PARTITION BY service) AS before_source
                  FROM (
                    SELECT
                      JSON_VALUE(resource.labels.service_name) AS service,
                      JSON_VALUE(resource.labels.revision_name) AS revision,
                      MIN(timestamp) AS first_request
                    FROM `prod-fin-observatory.dfo_logs._AllLogs`
                    WHERE resource.type = 'cloud_run_revision'
                      AND log_id = 'run.googleapis.com/requests'
                    GROUP BY service, revision
                  )
                ) AS seen
                WHERE NOT EXISTS (
                  SELECT 1
                  FROM `prod-fin-observatory.logs_daily.deploys` AS known
                  WHERE known.service = seen.service AND known.revision = seen.revision
                );
                
                COMMIT TRANSACTION;
            EOT
        }
      + project              = "prod-fin-observatory"
      + schedule             = "every day 02:00"
      + service_account_name = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
    }

  # google_bigquery_dataset.logs_daily will be created
  + resource "google_bigquery_dataset" "logs_daily" {
      + creation_time              = (known after apply)
      + dataset_id                 = "logs_daily"
      + default_collation          = (known after apply)
      + delete_contents_on_destroy = false
      + deletion_policy            = "DELETE"
      + description                = "Daily Cloud Run request, route, error and deploy aggregates, written by the dfo-prod-logs-daily scheduled query."
      + effective_labels           = {
          + "goog-terraform-provisioned" = "true"
        }
      + etag                       = (known after apply)
      + id                         = (known after apply)
      + is_case_insensitive        = (known after apply)
      + last_modified_time         = (known after apply)
      + location                   = "EU"
      + max_time_travel_hours      = (known after apply)
      + project                    = "prod-fin-observatory"
      + self_link                  = (known after apply)
      + storage_billing_model      = (known after apply)
      + terraform_labels           = {
          + "goog-terraform-provisioned" = "true"
        }

      + access (known after apply)
    }

  # google_bigquery_dataset.reporting will be created
  + resource "google_bigquery_dataset" "reporting" {
      + creation_time              = (known after apply)
      + dataset_id                 = "dfo_reporting"
      + default_collation          = (known after apply)
      + delete_contents_on_destroy = false
      + deletion_policy            = "DELETE"
      + description                = "Reporting views over the DFO telemetry datasets, read by the team dashboard."
      + effective_labels           = {
          + "goog-terraform-provisioned" = "true"
        }
      + etag                       = (known after apply)
      + id                         = (known after apply)
      + is_case_insensitive        = (known after apply)
      + last_modified_time         = (known after apply)
      + location                   = "EU"
      + max_time_travel_hours      = (known after apply)
      + project                    = "prod-fin-observatory"
      + self_link                  = (known after apply)
      + storage_billing_model      = (known after apply)
      + terraform_labels           = {
          + "goog-terraform-provisioned" = "true"
        }

      + access (known after apply)
    }

  # google_bigquery_dataset.searchconsole will be created
  + resource "google_bigquery_dataset" "searchconsole" {
      + creation_time              = (known after apply)
      + dataset_id                 = "searchconsole"
      + default_collation          = (known after apply)
      + delete_contents_on_destroy = false
      + deletion_policy            = "DELETE"
      + description                = "Search Console bulk data export for developmentfinance.org, written by search-console-data-export@system.gserviceaccount.com."
      + effective_labels           = {
          + "goog-terraform-provisioned" = "true"
        }
      + etag                       = (known after apply)
      + id                         = (known after apply)
      + is_case_insensitive        = (known after apply)
      + last_modified_time         = (known after apply)
      + location                   = "EU"
      + max_time_travel_hours      = (known after apply)
      + project                    = "prod-fin-observatory"
      + self_link                  = (known after apply)
      + storage_billing_model      = (known after apply)
      + terraform_labels           = {
          + "goog-terraform-provisioned" = "true"
        }

      + access (known after apply)
    }

  # google_bigquery_dataset_access.logs_daily_source_reader will be created
  + resource "google_bigquery_dataset_access" "logs_daily_source_reader" {
      + api_updated_member = (known after apply)
      + dataset_id         = "dfo_logs"
      + deletion_policy    = "DELETE"
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + role               = "READER"
      + user_by_email      = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
    }

  # google_bigquery_dataset_access.logs_daily_writer will be created
  + resource "google_bigquery_dataset_access" "logs_daily_writer" {
      + api_updated_member = (known after apply)
      + dataset_id         = "logs_daily"
      + deletion_policy    = "DELETE"
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + role               = "WRITER"
      + user_by_email      = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
    }

  # google_bigquery_dataset_access.reporting_readers["dashboard-readers"] will be created
  + resource "google_bigquery_dataset_access" "reporting_readers" {
      + api_updated_member = (known after apply)
      + dataset_id         = "dfo_reporting"
      + deletion_policy    = "DELETE"
      + group_by_email     = (sensitive value)
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + role               = "READER"
    }

  # google_bigquery_dataset_access.searchconsole_export_writer will be created
  + resource "google_bigquery_dataset_access" "searchconsole_export_writer" {
      + api_updated_member = (known after apply)
      + dataset_id         = "searchconsole"
      + deletion_policy    = "DELETE"
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + role               = "WRITER"
      + user_by_email      = "search-console-data-export@system.gserviceaccount.com"
    }

  # google_bigquery_routine.normalise_route will be created
  + resource "google_bigquery_routine" "normalise_route" {
      + creation_time      = (known after apply)
      + dataset_id         = "logs_daily"
      + definition_body    = <<-EOT
            -- Body of the logs_daily.normalise_route(url STRING) function. Cloud Run
            -- request logs carry the requested URL and no route template, so routes are
            -- recovered from the path's shape. The scheme, host, query string, fragment
            -- and trailing slashes go. Everything under /_next/static/ is content-hashed
            -- build output and becomes /_next/static/:asset. Any other segment becomes
            -- :id when it starts with a digit, holds an upper-case letter, is a UUID, or
            -- holds a digit with no hyphen or dot. That covers numbers, versions such as
            -- 1.0.0, hex digests, sha256:<hex> file ids, prefixed ids such as spec_<hex>
            -- and cmp_<ULID>, share ids, and dcids. API versions such as v1 stay, and so
            -- do lower-case words, hyphenated slugs and file names.
            -- tests/normalise_route.test.sh runs this file against recorded prod URLs.
            (
              SELECT
                CASE
                  WHEN path IS NULL THEN NULL
                  WHEN path = '' THEN '/'
                  WHEN STARTS_WITH(path, '/_next/static/') THEN '/_next/static/:asset'
                  ELSE ARRAY_TO_STRING(
                    ARRAY(
                      SELECT
                        CASE
                          WHEN REGEXP_CONTAINS(segment, r'^v[0-9]+$') THEN segment
                          WHEN REGEXP_CONTAINS(segment, r'^[0-9]') THEN ':id'
                          WHEN REGEXP_CONTAINS(segment, r'[A-Z]') THEN ':id'
                          WHEN REGEXP_CONTAINS(segment, r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') THEN ':id'
                          WHEN REGEXP_CONTAINS(segment, r'[0-9]') AND NOT REGEXP_CONTAINS(segment, r'[-.]') THEN ':id'
                          ELSE segment
                        END
                      FROM UNNEST(SPLIT(path, '/')) AS segment WITH OFFSET AS position
                      ORDER BY position
                    ),
                    '/'
                  )
                END
              FROM (
                SELECT RTRIM(REGEXP_EXTRACT(url, r'^(?:[A-Za-z][A-Za-z0-9+.-]*://[^/?#]*)?([^?#]*)'), '/') AS path
              )
            )
        EOT
      + deletion_policy    = "DELETE"
      + description        = "Route of a request URL: the path with id, dcid, hash and number segments as :id."
      + id                 = (known after apply)
      + language           = "SQL"
      + last_modified_time = (known after apply)
      + project            = "prod-fin-observatory"
      + return_type        = jsonencode(
            {
              + typeKind = "STRING"
            }
        )
      + routine_id         = "normalise_route"
      + routine_type       = "SCALAR_FUNCTION"

      + arguments {
          + argument_kind = "FIXED_TYPE"
          + data_type     = jsonencode(
                {
                  + typeKind = "STRING"
                }
            )
          + name          = "url"
        }
    }

  # google_logging_linked_dataset.telemetry will be created
  + resource "google_logging_linked_dataset" "telemetry" {
      + bucket          = (known after apply)
      + create_time     = (known after apply)
      + deletion_policy = (known after apply)
      + description     = "Log Analytics view of the dfo-prod-telemetry bucket."
      + id              = (known after apply)
      + lifecycle_state = (known after apply)
      + link_id         = "dfo_logs"
      + location        = (known after apply)
      + name            = (known after apply)
      + parent          = (known after apply)

      + bigquery_dataset (known after apply)
    }

  # google_logging_metric.logs_daily_failed will be created
  + resource "google_logging_metric" "logs_daily_failed" {
      + deletion_policy = "DELETE"
      + filter          = (known after apply)
      + id              = (known after apply)
      + name            = "dfo-prod-logs-daily-failed"
      + project         = "prod-fin-observatory"

      + metric_descriptor {
          + metric_kind = "DELTA"
          + unit        = "1"
          + value_type  = "INT64"
        }
    }

  # google_logging_project_bucket_config.telemetry will be created
  + resource "google_logging_project_bucket_config" "telemetry" {
      + bucket_id        = "dfo-prod-telemetry"
      + deletion_policy  = (known after apply)
      + description      = "Cloud Run request logs and service and job stdout and stderr, for logs_daily."
      + enable_analytics = true
      + id               = (known after apply)
      + lifecycle_state  = (known after apply)
      + location         = "eu"
      + name             = (known after apply)
      + project          = "prod-fin-observatory"
      + retention_days   = 30
    }

  # google_logging_project_sink.telemetry will be created
  + resource "google_logging_project_sink" "telemetry" {
      + deletion_policy        = "DELETE"
      + description            = "Routes Cloud Run request, stdout and stderr logs to the dfo-prod-telemetry bucket."
      + destination            = (known after apply)
      + filter                 = <<-EOT
            (resource.type="cloud_run_revision" OR resource.type="cloud_run_job")
            AND (log_id("run.googleapis.com/requests") OR log_id("run.googleapis.com/stdout") OR log_id("run.googleapis.com/stderr"))
            AND NOT (resource.labels.service_name="dfo-prod-website" AND jsonPayload.message="event")
        EOT
      + id                     = (known after apply)
      + name                   = "dfo-prod-telemetry"
      + project                = (known after apply)
      + unique_writer_identity = true
      + writer_identity        = (known after apply)

      + bigquery_options (known after apply)
    }

  # google_monitoring_alert_policy.export_job_failed["langfuse_export"] will be created
  + resource "google_monitoring_alert_policy" "export_job_failed" {
      + combiner              = "OR"
      + creation_record       = (known after apply)
      + deletion_policy       = "DELETE"
      + display_name          = "dfo-prod-langfuse-export Job execution failed"
      + enabled               = true
      + id                    = (known after apply)
      + name                  = (known after apply)
      + notification_channels = (known after apply)
      + project               = "prod-fin-observatory"

      + alert_strategy {
          + auto_close = "3600s"
        }

      + conditions {
          + display_name = "dfo-prod-langfuse-export execution completed as failed"
          + name         = (known after apply)

          + condition_threshold {
              + comparison      = "COMPARISON_GT"
              + duration        = "0s"
              + filter          = "resource.type=\"cloud_run_job\" AND resource.labels.job_name=\"dfo-prod-langfuse-export\" AND resource.labels.location=\"europe-west1\" AND metric.type=\"run.googleapis.com/job/completed_execution_count\" AND metric.labels.result=\"failed\""
              + threshold_value = 0

              + aggregations {
                  + alignment_period   = "900s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
    }

  # google_monitoring_alert_policy.export_job_failed["website_export"] will be created
  + resource "google_monitoring_alert_policy" "export_job_failed" {
      + combiner              = "OR"
      + creation_record       = (known after apply)
      + deletion_policy       = "DELETE"
      + display_name          = "dfo-prod-website-export Job execution failed"
      + enabled               = true
      + id                    = (known after apply)
      + name                  = (known after apply)
      + notification_channels = (known after apply)
      + project               = "prod-fin-observatory"

      + alert_strategy {
          + auto_close = "3600s"
        }

      + conditions {
          + display_name = "dfo-prod-website-export execution completed as failed"
          + name         = (known after apply)

          + condition_threshold {
              + comparison      = "COMPARISON_GT"
              + duration        = "0s"
              + filter          = "resource.type=\"cloud_run_job\" AND resource.labels.job_name=\"dfo-prod-website-export\" AND resource.labels.location=\"europe-west1\" AND metric.type=\"run.googleapis.com/job/completed_execution_count\" AND metric.labels.result=\"failed\""
              + threshold_value = 0

              + aggregations {
                  + alignment_period   = "900s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
    }

  # google_monitoring_alert_policy.export_job_not_succeeding["langfuse_export"] will be created
  + resource "google_monitoring_alert_policy" "export_job_not_succeeding" {
      + combiner              = "OR"
      + creation_record       = (known after apply)
      + deletion_policy       = "DELETE"
      + display_name          = "dfo-prod-langfuse-export Job not succeeding"
      + enabled               = true
      + id                    = (known after apply)
      + name                  = (known after apply)
      + notification_channels = (known after apply)
      + project               = "prod-fin-observatory"

      + alert_strategy {
          + auto_close = "604800s"
        }

      + conditions {
          + display_name = "no succeeded dfo-prod-langfuse-export execution for 10800s"
          + name         = (known after apply)

          + condition_absent {
              + duration = "10800s"
              + filter   = "resource.type=\"cloud_run_job\" AND resource.labels.job_name=\"dfo-prod-langfuse-export\" AND resource.labels.location=\"europe-west1\" AND metric.type=\"run.googleapis.com/job/completed_execution_count\" AND metric.labels.result=\"succeeded\""

              + aggregations {
                  + alignment_period   = "900s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
    }

  # google_monitoring_alert_policy.export_job_not_succeeding["website_export"] will be created
  + resource "google_monitoring_alert_policy" "export_job_not_succeeding" {
      + combiner              = "OR"
      + creation_record       = (known after apply)
      + deletion_policy       = "DELETE"
      + display_name          = "dfo-prod-website-export Job not succeeding"
      + enabled               = true
      + id                    = (known after apply)
      + name                  = (known after apply)
      + notification_channels = (known after apply)
      + project               = "prod-fin-observatory"

      + alert_strategy {
          + auto_close = "604800s"
        }

      + conditions {
          + display_name = "no succeeded dfo-prod-website-export execution for 10800s"
          + name         = (known after apply)

          + condition_absent {
              + duration = "10800s"
              + filter   = "resource.type=\"cloud_run_job\" AND resource.labels.job_name=\"dfo-prod-website-export\" AND resource.labels.location=\"europe-west1\" AND metric.type=\"run.googleapis.com/job/completed_execution_count\" AND metric.labels.result=\"succeeded\""

              + aggregations {
                  + alignment_period   = "900s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
    }

  # google_monitoring_alert_policy.logs_daily_failed will be created
  + resource "google_monitoring_alert_policy" "logs_daily_failed" {
      + combiner              = "OR"
      + creation_record       = (known after apply)
      + deletion_policy       = "DELETE"
      + display_name          = "logs_daily scheduled query failed"
      + enabled               = true
      + id                    = (known after apply)
      + name                  = (known after apply)
      + notification_channels = (known after apply)
      + project               = "prod-fin-observatory"

      + alert_strategy {
          + auto_close = "86400s"
        }

      + conditions {
          + display_name = "logs_daily run logged an error"
          + name         = (known after apply)

          + condition_threshold {
              + comparison      = "COMPARISON_GT"
              + duration        = "0s"
              + filter          = "resource.type=\"bigquery_dts_config\" AND metric.type=\"logging.googleapis.com/user/dfo-prod-logs-daily-failed\""
              + threshold_value = 0

              + aggregations {
                  + alignment_period   = "300s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
      + conditions {
          + display_name = "logs_daily run completed as FAILED"
          + name         = (known after apply)

          + condition_threshold {
              + comparison      = "COMPARISON_GT"
              + duration        = "0s"
              + filter          = (known after apply)
              + threshold_value = 0

              + aggregations {
                  + alignment_period   = "300s"
                  + per_series_aligner = "ALIGN_SUM"
                }
            }
        }
    }

  # google_monitoring_notification_channel.alert_email["team"] will be created
  + resource "google_monitoring_notification_channel" "alert_email" {
      + deletion_policy     = "DELETE"
      + display_name        = "Telemetry pipeline alerts: team"
      + enabled             = true
      + force_delete        = false
      + id                  = (known after apply)
      + labels              = {
          + "email_address" = (sensitive value)
        }
      + name                = (known after apply)
      + project             = "prod-fin-observatory"
      + type                = "email"
      + verification_status = (known after apply)
    }

  # google_project_iam_member.logs_daily_job_user will be created
  + resource "google_project_iam_member" "logs_daily_job_user" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/bigquery.jobUser"
    }

  # google_project_iam_member.reporting_readers_job_user["dashboard-readers"] will be created
  + resource "google_project_iam_member" "reporting_readers_job_user" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/bigquery.jobUser"
    }

  # google_project_iam_member.reporting_readers_mcp_tool_user["dashboard-readers"] will be created
  + resource "google_project_iam_member" "reporting_readers_mcp_tool_user" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/mcp.toolUser"
    }

  # google_project_iam_member.searchconsole_export_job_user will be created
  + resource "google_project_iam_member" "searchconsole_export_job_user" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:search-console-data-export@system.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/bigquery.jobUser"
    }

  # google_project_service.apis["bigquery.googleapis.com"] will be created
  + resource "google_project_service" "apis" {
      + deletion_policy    = "DELETE"
      + disable_on_destroy = false
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + service            = "bigquery.googleapis.com"
    }

  # google_project_service.apis["bigquerydatatransfer.googleapis.com"] will be created
  + resource "google_project_service" "apis" {
      + deletion_policy    = "DELETE"
      + disable_on_destroy = false
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + service            = "bigquerydatatransfer.googleapis.com"
    }

  # google_project_service.apis["logging.googleapis.com"] will be created
  + resource "google_project_service" "apis" {
      + deletion_policy    = "DELETE"
      + disable_on_destroy = false
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + service            = "logging.googleapis.com"
    }

  # google_service_account.logs_daily will be created
  + resource "google_service_account" "logs_daily" {
      + account_id      = "dfo-prod-logs-daily"
      + deletion_policy = "DELETE"
      + description     = "Runs the logs_daily scheduled query: reads dfo_logs, writes logs_daily."
      + disabled        = false
      + display_name    = "dfo-prod logs_daily scheduled query"
      + email           = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
      + id              = (known after apply)
      + member          = "serviceAccount:dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
      + name            = (known after apply)
      + project         = "prod-fin-observatory"
      + unique_id       = (known after apply)
    }

  # google_service_account_iam_member.logs_daily_transfer_agent will be created
  + resource "google_service_account_iam_member" "logs_daily_transfer_agent" {
      + etag               = (known after apply)
      + id                 = (known after apply)
      + member             = "serviceAccount:service-533754688761@gcp-sa-bigquerydatatransfer.iam.gserviceaccount.com"
      + role               = "roles/iam.serviceAccountTokenCreator"
      + service_account_id = (known after apply)
    }

  # time_sleep.logs_daily_failed_metric_propagation will be created
  + resource "time_sleep" "logs_daily_failed_metric_propagation" {
      + create_duration = "120s"
      + id              = (known after apply)
    }

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

Changes to Outputs:
  + logs_daily_dataset         = "prod-fin-observatory.logs_daily"
  + logs_daily_service_account = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
  + logs_linked_dataset        = "prod-fin-observatory.dfo_logs"
  + reporting_dataset          = "prod-fin-observatory.dfo_reporting"
  + searchconsole_dataset      = "searchconsole"

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

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

Stack telemetry · b52ff45 · @jm-rivera · run

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Terraform Plan — foundation

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

Init Validate Plan
pass pass pass
Show plan
google_project_service.apis["sts.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/sts.googleapis.com]
google_project_service.apis["cloudresourcemanager.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/cloudresourcemanager.googleapis.com]
module.principals.data.google_secret_manager_secret_version.this: Reading...
google_project_service.apis["iam.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/iam.googleapis.com]
google_project_service.apis["workflows.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/workflows.googleapis.com]
google_project_service.apis["iamcredentials.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/iamcredentials.googleapis.com]
google_project_service.apis["drive.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/drive.googleapis.com]
google_project_iam_custom_role.applier_transfer_configs: Refreshing state... [id=projects/prod-fin-observatory/roles/dfoInfraApplierTransferConfigs]
google_project_service.billing_export_bigquery[0]: Refreshing state... [id=prod-fin-observatory/bigquery.googleapis.com]
google_project_service.apis["artifactregistry.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/artifactregistry.googleapis.com]
module.principals.data.google_secret_manager_secret_version.this: Read complete after 1s [id=projects/533754688761/secrets/dfo-prod-foundation-principals/versions/1]
google_project_service.apis["docs.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/docs.googleapis.com]
google_project_service.apis["sheets.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/sheets.googleapis.com]
data.google_project.this: Reading...
google_bigquery_dataset.billing_export[0]: Refreshing state... [id=projects/prod-fin-observatory/datasets/billing_export]
google_iam_workload_identity_pool.github: Refreshing state... [id=projects/prod-fin-observatory/locations/global/workloadIdentityPools/github-pool]
google_artifact_registry_repository.dcp_build_cache: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/dfo-dcp-build-cache]
google_artifact_registry_repository.website: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/dfo-website]
module.docs_sync.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-docs-sync@prod-fin-observatory.iam.gserviceaccount.com]
module.planner.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
google_artifact_registry_repository.datacommons: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/datacommons]
module.apis_deployer.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-apis-deployer@prod-fin-observatory.iam.gserviceaccount.com]
google_project_service_identity.workflows: Refreshing state... [id=projects/prod-fin-observatory/services/workflows.googleapis.com]
module.website_deployer.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-website-deployer@prod-fin-observatory.iam.gserviceaccount.com]
data.google_project.this: Read complete after 1s [id=projects/prod-fin-observatory]
module.applier.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_deployer.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.dcp_deployer.google_service_account.this: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-dcp-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.planner.google_project_iam_member.project_roles["roles/viewer"]: Refreshing state... [id=prod-fin-observatory/roles/viewer/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
module.planner.google_storage_bucket_iam_member.state_bucket[0]: Refreshing state... [id=b/tf-state-dfo-prod-prod-fin-observatory/roles/storage.objectViewer/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com/state-bucket-object-prefixes//(resource.type == "storage.googleapis.com/Bucket" && resource.name == "projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory") || (resource.type == "storage.googleapis.com/Object" && (resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/foundation/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/ai/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/apis/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/website/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/dcp/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/platform/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/pipelines/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/edge/") || resource.name.startsWith("projects/_/buckets/tf-state-dfo-prod-prod-fin-observatory/objects/terraform/state/dfo-prod/telemetry/")))]
module.planner.google_project_iam_member.project_roles["roles/serviceusage.serviceUsageConsumer"]: Refreshing state... [id=prod-fin-observatory/roles/serviceusage.serviceUsageConsumer/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
module.planner.google_project_iam_member.project_roles["roles/iam.securityReviewer"]: Refreshing state... [id=prod-fin-observatory/roles/iam.securityReviewer/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
google_secret_manager_secret_iam_member.dc_key_planner: Refreshing state... [id=projects/prod-fin-observatory/secrets/dc-api-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/bigquery.dataOwner"]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.dataOwner/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/compute.loadBalancerAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/compute.loadBalancerAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/spanner.admin"]: Refreshing state... [id=prod-fin-observatory/roles/spanner.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/secretmanager.admin"]: Refreshing state... [id=prod-fin-observatory/roles/secretmanager.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/bigquery.jobUser"]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.jobUser/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/iam.serviceAccountUser"]: Refreshing state... [id=prod-fin-observatory/roles/iam.serviceAccountUser/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/certificatemanager.editor"]: Refreshing state... [id=prod-fin-observatory/roles/certificatemanager.editor/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/resourcemanager.projectIamAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/resourcemanager.projectIamAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/compute.networkViewer"]: Refreshing state... [id=prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/cloudtasks.queueAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/cloudtasks.queueAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/redis.admin"]: Refreshing state... [id=prod-fin-observatory/roles/redis.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/monitoring.alertPolicyEditor"]: Refreshing state... [id=prod-fin-observatory/roles/monitoring.alertPolicyEditor/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/iam.serviceAccountAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/iam.serviceAccountAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/cloudsql.admin"]: Refreshing state... [id=prod-fin-observatory/roles/cloudsql.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/bigquery.resourceAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.resourceAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/monitoring.notificationChannelEditor"]: Refreshing state... [id=prod-fin-observatory/roles/monitoring.notificationChannelEditor/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/serviceusage.apiKeysAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/serviceusage.apiKeysAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/compute.securityAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/compute.securityAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/iam.workloadIdentityPoolAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/iam.workloadIdentityPoolAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/cloudscheduler.admin"]: Refreshing state... [id=prod-fin-observatory/roles/cloudscheduler.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/dns.admin"]: Refreshing state... [id=prod-fin-observatory/roles/dns.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/workflows.admin"]: Refreshing state... [id=prod-fin-observatory/roles/workflows.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/logging.configWriter"]: Refreshing state... [id=prod-fin-observatory/roles/logging.configWriter/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/run.admin"]: Refreshing state... [id=prod-fin-observatory/roles/run.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/storage.admin"]: Refreshing state... [id=prod-fin-observatory/roles/storage.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/bigquery.connectionAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.connectionAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/artifactregistry.admin"]: Refreshing state... [id=prod-fin-observatory/roles/artifactregistry.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/compute.networkAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/compute.networkAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/vpcaccess.admin"]: Refreshing state... [id=prod-fin-observatory/roles/vpcaccess.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/iam.roleAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/iam.roleAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/serviceusage.serviceUsageAdmin"]: Refreshing state... [id=prod-fin-observatory/roles/serviceusage.serviceUsageAdmin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
google_iam_workload_identity_pool_provider.github: Refreshing state... [id=projects/prod-fin-observatory/locations/global/workloadIdentityPools/github-pool/providers/github]
google_project_iam_member.applier_transfer_configs: Refreshing state... [id=prod-fin-observatory/projects/prod-fin-observatory/roles/dfoInfraApplierTransferConfigs/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.apis_deployer.google_artifact_registry_repository_iam_member.repository_roles["europe-west1:datacommons:roles/artifactregistry.writer"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/datacommons/roles/artifactregistry.writer/serviceAccount:dfo-apis-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_deployer.google_artifact_registry_repository_iam_member.repository_roles["europe-west1:datacommons:roles/artifactregistry.writer"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/datacommons/roles/artifactregistry.writer/serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.dcp_deployer.google_artifact_registry_repository_iam_member.repository_roles["europe-west1:datacommons:roles/artifactregistry.writer"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/datacommons/roles/artifactregistry.writer/serviceAccount:dfo-dcp-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.dcp_deployer.google_artifact_registry_repository_iam_member.repository_roles["europe-west1:dfo-dcp-build-cache:roles/artifactregistry.writer"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/dfo-dcp-build-cache/roles/artifactregistry.writer/serviceAccount:dfo-dcp-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.website_deployer.google_artifact_registry_repository_iam_member.repository_roles["europe-west1:dfo-website:roles/artifactregistry.writer"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/repositories/dfo-website/roles/artifactregistry.writer/serviceAccount:dfo-website-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.docs_sync.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-docs-sync@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_ref/1401634043:refs/heads/main]
module.apis_deployer.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-apis-deployer@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1401633649:production:refs/heads/main]
module.dcp_deployer.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-dcp-deployer@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1431071058:production:refs/heads/main]
module.ai_deployer.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1401633727:production:refs/heads/main]
module.planner.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1401633456:plan:refs/heads/main]
module.website_deployer.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-website-deployer@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1401633828:production:refs/heads/main]
module.applier.google_service_account_iam_member.wif: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.workloadIdentityUser/principalSet://iam.googleapis.com/projects/533754688761/locations/global/workloadIdentityPools/github-pool/attribute.repo_env_ref/1401633456:production:refs/heads/main]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

 # google_project_iam_member.ingestion_operator_viewer["*** roles/dataflow.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/dataflow.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/logging.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/logging.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/monitoring.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/monitoring.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/run.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/run.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/serviceusage.serviceUsageConsumer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/serviceusage.serviceUsageConsumer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/spanner.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/spanner.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/storage.bucketViewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/storage.bucketViewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_viewer["*** roles/workflows.viewer"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_viewer" {
        id      = "prod-fin-observatory/roles/workflows.viewer/***"
        # (4 unchanged attributes hidden)
    }

 # google_project_iam_member.ingestion_operator_workflow_invoker["***"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_project_iam_member" "ingestion_operator_workflow_invoker" {
        id      = "prod-fin-observatory/roles/workflows.invoker/***"
        # (4 unchanged attributes hidden)
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/batch.jobsViewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/batch.jobsViewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/dataflow.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/dataflow.viewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/logging.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/logging.viewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/monitoring.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/monitoring.viewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/run.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/run.viewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/serviceusage.serviceUsageConsumer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/serviceusage.serviceUsageConsumer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/spanner.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/spanner.viewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/storage.bucketViewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/storage.bucketViewer"
    }

  # google_project_iam_member.ingestion_viewer["prod-ingestion roles/workflows.viewer"] will be created
  + resource "google_project_iam_member" "ingestion_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/workflows.viewer"
    }

  # google_project_iam_member.ingestion_workflow_invoker["prod-ingestion"] will be created
  + resource "google_project_iam_member" "ingestion_workflow_invoker" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = (sensitive value)
      + project = "prod-fin-observatory"
      + role    = "roles/workflows.invoker"
    }

  # google_secret_manager_secret_iam_member.principals_planner["dfo-prod-ai-principals"] will be created
  + resource "google_secret_manager_secret_iam_member" "principals_planner" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = (known after apply)
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "projects/prod-fin-observatory/secrets/dfo-prod-ai-principals"
    }

  # google_secret_manager_secret_iam_member.principals_planner["dfo-prod-foundation-principals"] will be created
  + resource "google_secret_manager_secret_iam_member" "principals_planner" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = (known after apply)
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "projects/prod-fin-observatory/secrets/dfo-prod-foundation-principals"
    }

  # google_secret_manager_secret_iam_member.principals_planner["dfo-prod-telemetry-principals"] will be created
  + resource "google_secret_manager_secret_iam_member" "principals_planner" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = (known after apply)
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "projects/prod-fin-observatory/secrets/dfo-prod-telemetry-principals"
    }

 # google_service_account_iam_member.ingestion_operator_workflow_token_creator["***"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_service_account_iam_member" "ingestion_operator_workflow_token_creator" {
        id                 = "projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/***"
        # (4 unchanged attributes hidden)
    }

  # google_service_account_iam_member.ingestion_workflow_token_creator["prod-ingestion"] will be created
  + resource "google_service_account_iam_member" "ingestion_workflow_token_creator" {
      + etag               = (known after apply)
      + id                 = (known after apply)
      + member             = (sensitive value)
      + role               = "roles/iam.serviceAccountTokenCreator"
      + service_account_id = "projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com"
    }

  # google_spanner_database_iam_member.ingestion_database_reader["prod-ingestion"] will be created
  + resource "google_spanner_database_iam_member" "ingestion_database_reader" {
      + database = "dfo-prod-dc-db"
      + etag     = (known after apply)
      + id       = (known after apply)
      + instance = "dfo-prod-dc-instance"
      + member   = (sensitive value)
      + project  = (known after apply)
      + role     = "roles/spanner.databaseReader"
    }

 # google_spanner_database_iam_member.ingestion_operator_database_reader["***"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_spanner_database_iam_member" "ingestion_operator_database_reader" {
        id       = "prod-fin-observatory/dfo-prod-dc-instance/dfo-prod-dc-db/roles/spanner.databaseReader/***"
        # (5 unchanged attributes hidden)
    }

  # google_storage_bucket_iam_member.ingestion_artifacts_writer["prod-ingestion"] will be created
  + resource "google_storage_bucket_iam_member" "ingestion_artifacts_writer" {
      + bucket = "dfo-prod-dc-artifacts-prod-fin-observatory"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = (sensitive value)
      + role   = "roles/storage.objectUser"
    }

 # google_storage_bucket_iam_member.ingestion_operator_artifacts_writer["***"] will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "google_storage_bucket_iam_member" "ingestion_operator_artifacts_writer" {
        id     = "b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectUser/***"
        # (4 unchanged attributes hidden)
    }

  # module.applier.google_project_iam_member.project_roles["roles/compute.networkViewer"] will be destroyed
  # (because key ["roles/compute.networkViewer"] is not in for_each map)
  - resource "google_project_iam_member" "project_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/compute.networkViewer" -> null
    }

  # module.applier.google_project_iam_member.project_roles["roles/vpcaccess.admin"] will be destroyed
  # (because key ["roles/vpcaccess.admin"] is not in for_each map)
  - resource "google_project_iam_member" "project_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/vpcaccess.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/vpcaccess.admin" -> null
    }

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

Warning: Some objects will no longer be managed by Terraform

If you apply this plan, Terraform will discard its tracking information for
the following objects, but it will not delete them:
 - google_project_iam_member.ingestion_operator_viewer["*** roles/spanner.viewer"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/run.viewer"]
 - google_spanner_database_iam_member.ingestion_operator_database_reader["***"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/monitoring.viewer"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/workflows.viewer"]
 - google_project_iam_member.ingestion_operator_workflow_invoker["***"]
 - google_storage_bucket_iam_member.ingestion_operator_artifacts_writer["***"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/dataflow.viewer"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/serviceusage.serviceUsageConsumer"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/logging.viewer"]
 - google_service_account_iam_member.ingestion_operator_workflow_token_creator["***"]
 - google_project_iam_member.ingestion_operator_viewer["*** roles/storage.bucketViewer"]

After applying this plan, Terraform will no longer manage these objects. You
will need to import them into Terraform to manage them again.

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

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

Stack foundation · b52ff45 · @jm-rivera · run

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Terraform Plan — ai

No changes. Infrastructure matches configuration.

Init Validate Plan
pass pass pass
Show plan
ephemeral.random_password.studio_api_token: Opening...
ephemeral.random_password.mcp_api_token: Opening...
ephemeral.random_password.studio_api_token: Opening complete after 0s
ephemeral.random_password.mcp_api_token: Opening complete after 0s
data.google_secret_manager_secret.langfuse_secret_key: Reading...
google_project_service.dns: Refreshing state... [id=prod-fin-observatory/dns.googleapis.com]
google_service_account.langfuse_export_scheduler[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-langfuse-scheduler@prod-fin-observatory.iam.gserviceaccount.com]
data.google_service_account.ai_deployer: Reading...
data.google_secret_manager_secret.gemini: Reading...
google_project_iam_custom_role.cloudsql_login_only: Refreshing state... [id=projects/prod-fin-observatory/roles/dfoProdAiCloudsqlLoginOnly]
module.principals.data.google_secret_manager_secret_version.this: Reading...
google_secret_manager_secret.mcp_api_token: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-mcp-api-token]
google_sql_database.ai_sessions: Refreshing state... [id=projects/prod-fin-observatory/instances/dfo-prod-platform-postgres/databases/ai-sessions]
google_storage_bucket.definition_store: Refreshing state... [id=prod-fin-observatory-ai-definition-store]
data.google_secret_manager_secret.langfuse_secret_key: Read complete after 0s [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-secret-key]
data.google_secret_manager_secret.langfuse_public_key: Reading...
module.ai_service.google_service_account.runtime: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
data.google_secret_manager_secret.gemini: Read complete after 0s [id=projects/prod-fin-observatory/secrets/dfo-prod-gemini-api-key]
google_secret_manager_secret.studio_api_token: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-studio-api-token]
data.google_service_account.ai_deployer: Read complete after 0s [id=projects/prod-fin-observatory/serviceAccounts/dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
google_project_service.langfuse_export_cloudscheduler[0]: Refreshing state... [id=prod-fin-observatory/cloudscheduler.googleapis.com]
google_project_service.langfuse_export_bigquery[0]: Refreshing state... [id=prod-fin-observatory/bigquery.googleapis.com]
google_storage_bucket.materialisation_store: Refreshing state... [id=prod-fin-observatory-ai-materialisation-store]
google_service_account.langfuse_export[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-langfuse-export@prod-fin-observatory.iam.gserviceaccount.com]
module.principals.data.google_secret_manager_secret_version.this: Read complete after 0s [id=projects/533754688761/secrets/dfo-prod-ai-principals/versions/1]
google_secret_manager_secret_version.mcp_api_token: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-mcp-api-token/versions/1]
data.google_secret_manager_secret.langfuse_public_key: Read complete after 0s [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-public-key]
module.ai_service.google_service_account_iam_member.deployer_act_as["serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com"]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
google_cloud_run_v2_service_iam_member.ai_apis_invoker: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-apis/roles/run.invoker/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_storage_bucket_iam_member.definition_store_viewer: Refreshing state... [id=b/prod-fin-observatory-ai-definition-store/roles/storage.objectViewer/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_project_iam_member.ai_cloudsql_client: Refreshing state... [id=prod-fin-observatory/roles/cloudsql.client/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_sql_user.ai_sessions_runtime: Refreshing state... [id=dfo-prod-ai-run@prod-fin-observatory.iam//dfo-prod-platform-postgres]
google_storage_bucket_iam_member.definition_store_creator: Refreshing state... [id=b/prod-fin-observatory-ai-definition-store/roles/storage.objectCreator/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_secret_manager_secret_version.studio_api_token: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-studio-api-token/versions/1]
google_project_iam_member.langfuse_export_bigquery_job_user[0]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.jobUser/serviceAccount:dfo-prod-langfuse-export@prod-fin-observatory.iam.gserviceaccount.com]
google_service_account_iam_member.langfuse_export_deployer_act_as[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-langfuse-export@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
google_secret_manager_secret_iam_member.langfuse_export_secret_access["public"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-public-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-langfuse-export@prod-fin-observatory.iam.gserviceaccount.com]
google_secret_manager_secret_iam_member.langfuse_export_secret_access["secret"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-secret-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-langfuse-export@prod-fin-observatory.iam.gserviceaccount.com]
google_project_iam_member.ai_cloudsql_login: Refreshing state... [id=prod-fin-observatory/projects/prod-fin-observatory/roles/dfoProdAiCloudsqlLoginOnly/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_storage_bucket_iam_member.materialisation_store_viewer: Refreshing state... [id=b/prod-fin-observatory-ai-materialisation-store/roles/storage.objectViewer/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_storage_bucket_iam_member.materialisation_store_creator: Refreshing state... [id=b/prod-fin-observatory-ai-materialisation-store/roles/storage.objectCreator/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-datasets-first-party-principal"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-datasets-first-party-principal/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-gemini-api-key"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-gemini-api-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-langfuse-secret-key"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-secret-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-mcp-api-token"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-mcp-api-token/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-live-refresh-principal"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-live-refresh-principal/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-langfuse-public-key"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-langfuse-public-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_secret_manager_secret_iam_member.runtime_secret_access["dfo-prod-studio-api-token"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-studio-api-token/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com]
google_sql_provision_script.ai_sessions_revoke_public_connect: Refreshing state... [id=prod-fin-observatory/dfo-prod-platform-postgres]
google_sql_provision_script.ai_sessions_schema_grant: Refreshing state... [id=prod-fin-observatory/dfo-prod-platform-postgres]
module.psc_network.google_compute_network.this: Refreshing state... [id=projects/prod-fin-observatory/global/networks/dfo-prod-ai-psc]
google_bigquery_dataset.langfuse_export[0]: Refreshing state... [id=projects/prod-fin-observatory/datasets/langfuse_export]
module.psc_network.google_compute_subnetwork.this: Refreshing state... [id=projects/prod-fin-observatory/regions/europe-west1/subnetworks/dfo-prod-ai-psc-subnet]
module.psc_network.google_dns_managed_zone.psc: Refreshing state... [id=projects/prod-fin-observatory/managedZones/dfo-prod-ai-psc-sql]
google_bigquery_dataset_access.langfuse_export_writer[0]: Refreshing state... [id=projects/prod-fin-observatory/datasets/langfuse_export]
module.psc_network.google_compute_address.psc_endpoint: Refreshing state... [id=projects/prod-fin-observatory/regions/europe-west1/addresses/dfo-prod-ai-psc-endpoint]
module.ai_service.google_cloud_run_v2_service.this: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-ai]
module.psc_network.google_dns_record_set.psc: Refreshing state... [id=projects/prod-fin-observatory/managedZones/dfo-prod-ai-psc-sql/rrsets/b588fda303da.1b8f7kohjv63q.europe-west1.sql.goog./A]
module.psc_network.google_compute_forwarding_rule.psc_endpoint: Refreshing state... [id=projects/prod-fin-observatory/regions/europe-west1/forwardingRules/dfo-prod-ai-psc-fwd]
module.ai_service.google_cloud_run_v2_service_iam_member.deployer_run_developer["serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com"]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-ai/roles/run.developer/serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
module.ai_service.google_cloud_run_v2_service_iam_member.public[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-ai/roles/run.invoker/allUsers]
google_cloud_run_v2_job.langfuse_export[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-langfuse-export]
google_cloud_run_v2_job_iam_member.langfuse_export_deployer_run_developer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-langfuse-export/roles/run.developer/serviceAccount:dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com]
google_cloud_run_v2_job_iam_member.langfuse_export_scheduler_invoker[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-langfuse-export/roles/run.invoker/serviceAccount:dfo-prod-langfuse-scheduler@prod-fin-observatory.iam.gserviceaccount.com]
google_cloud_scheduler_job.langfuse_export[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-langfuse-export-tick]
ephemeral.random_password.studio_api_token: Closing...
ephemeral.random_password.mcp_api_token: Closing...
ephemeral.random_password.mcp_api_token: Closing complete after 0s
ephemeral.random_password.studio_api_token: Closing complete after 0s

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.

Stack ai · b52ff45 · @jm-rivera · run

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Terraform Plan — dcp

Plan: 17 to add, 4 to change, 16 to destroy.

Init Validate Plan
pass pass pass
Show plan
ephemeral.random_password.presentation_migrator: Opening...
ephemeral.random_password.datasets_migrator: Opening...
ephemeral.random_password.presentation_migrator: Opening complete after 0s
ephemeral.random_password.datasets_migrator: Opening complete after 0s
google_sql_database.presentation: Refreshing state... [id=projects/prod-fin-observatory/instances/dfo-prod-platform-postgres/databases/presentation]
data.google_secret_manager_secret_version.dc_key: Reading...
google_project_service.apis["bigqueryreservation.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/bigqueryreservation.googleapis.com]
google_secret_manager_secret.datasets_migrator_password: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-datasets-migrator-password]
google_project_service.apis["maps-backend.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/maps-backend.googleapis.com]
google_project_service.apis["dataflow.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/dataflow.googleapis.com]
google_project_service.apis["secretmanager.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/secretmanager.googleapis.com]
google_sql_database.datasets: Refreshing state... [id=projects/prod-fin-observatory/instances/dfo-prod-platform-postgres/databases/datasets]
google_storage_bucket.dc_artifacts: Refreshing state... [id=dfo-prod-dc-artifacts-prod-fin-observatory]
google_storage_bucket.datasets_working: Refreshing state... [id=prod-fin-observatory-datasets-working]
google_project_service.apis["compute.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/compute.googleapis.com]
google_project_service.apis["iam.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/iam.googleapis.com]
data.google_secret_manager_secret_version.dc_key: Read complete after 0s [id=projects/533754688761/secrets/dc-api-key/versions/2]
google_project_service.apis["bigquery.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/bigquery.googleapis.com]
google_project_service.apis["cloudresourcemanager.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/cloudresourcemanager.googleapis.com]
google_project_service.apis["redis.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/redis.googleapis.com]
google_project_service.apis["artifactregistry.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/artifactregistry.googleapis.com]
google_project_service.apis["aiplatform.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/aiplatform.googleapis.com]
google_project_service.apis["workflowexecutions.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/workflowexecutions.googleapis.com]
google_project_service.apis["bigqueryconnection.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/bigqueryconnection.googleapis.com]
google_project_service.apis["places-backend.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/places-backend.googleapis.com]
google_project_service.apis["apikeys.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/apikeys.googleapis.com]
google_project_service.apis["sqladmin.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/sqladmin.googleapis.com]
google_project_service.apis["run.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/run.googleapis.com]
google_project_service.apis["spanner.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/spanner.googleapis.com]
google_project_service.apis["workflows.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/workflows.googleapis.com]
google_project_service.apis["vpcaccess.googleapis.com"]: Refreshing state... [id=prod-fin-observatory/vpcaccess.googleapis.com]
google_sql_user.presentation_migrator: Refreshing state... [id=dfo-prod-presentation-migrator//dfo-prod-platform-postgres]
null_resource.dc_key_guard: Refreshing state... [id=8991251217037466127]
data.google_secret_manager_secret.search_api_gemini: Reading...
google_secret_manager_secret_version.datasets_migrator_password: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-datasets-migrator-password/versions/1]
google_secret_manager_secret.presentation_migrator_password: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-presentation-migrator-password]
google_service_account.datasets_gc: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-datasets-gc-sa@prod-fin-observatory.iam.gserviceaccount.com]
google_sql_user.datasets_migrator: Refreshing state... [id=dfo-prod-datasets-migrator//dfo-prod-platform-postgres]
google_storage_bucket.datasets_pinned: Refreshing state... [id=prod-fin-observatory-datasets-pinned]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_invoker[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_viewer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.viewer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
data.google_secret_manager_secret.search_api_gemini: Read complete after 1s [id=projects/prod-fin-observatory/secrets/dfo-prod-gemini-api-key]
module.stack.module.auth.random_id.api_key_suffix: Refreshing state... [id=dBpGog]
google_secret_manager_secret_version.presentation_migrator_password: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-presentation-migrator-password/versions/1]
module.stack.module.ingestion_helper_service.google_service_account.helper_sa[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-hlp-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.auth.google_secret_manager_secret.dc_api_key: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-dc-api-key]
module.stack.module.auth.google_apikeys_key.maps_api_key[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/global/keys/dfo-prod-dc-google-maps-key-741a46a2]
module.stack.module.ingestion_dataflow.google_service_account.dataflow_sa[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.auth.google_secret_manager_secret.maps_api_key[0]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-dc-google-maps-api-key-741a46a2]
module.stack.module.spanner[0].google_bigquery_reservation.default[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/reservations/default]
module.stack.module.ingestion_postprocessing_job[0].google_service_account.postprocessing_sa: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com]
google_sql_user.datasets_gc: Refreshing state... [id=dfo-prod-dc-datasets-gc-sa@prod-fin-observatory.iam//dfo-prod-platform-postgres]
google_storage_bucket_iam_member.datasets_pinned_gc_admin: Refreshing state... [id=b/prod-fin-observatory-datasets-pinned/roles/storage.objectAdmin/serviceAccount:dfo-prod-dc-datasets-gc-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_helper_service.google_project_iam_member.helper_dataflow_viewer[0]: Refreshing state... [id=prod-fin-observatory/roles/dataflow.viewer/serviceAccount:dfo-prod-dc-ing-hlp-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_helper_service.google_project_iam_member.helper_spanner_user[0]: Refreshing state... [id=prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-ing-hlp-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_project_iam_member.bq_sa_spanner_viewer[0]: Refreshing state... [id=prod-fin-observatory/roles/spanner.viewer/serviceAccount:bq-533754688761@bigquery-encryption.iam.gserviceaccount.com]
module.stack.module.auth.google_secret_manager_secret_version.dc_api_key_version: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-dc-api-key/versions/1]
module.stack.module.ingestion_dataflow.google_service_account_iam_member.workflows_token_creator[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/serviceAccount:service-533754688761@gcp-sa-workflows.iam.gserviceaccount.com]
module.stack.module.ingestion_dataflow.google_project_iam_member.dataflow_worker[0]: Refreshing state... [id=prod-fin-observatory/roles/dataflow.worker/serviceAccount:dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_dataflow.google_project_iam_member.ingestion_spanner_user[0]: Refreshing state... [id=prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_postprocessing_job[0].google_project_iam_member.postprocessing_bq_connection_user[0]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.connectionUser/serviceAccount:dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_postprocessing_job[0].google_project_iam_member.postprocessing_bq_job_user[0]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.jobUser/serviceAccount:dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_postprocessing_job[0].google_project_iam_member.postprocessing_bq_data_editor[0]: Refreshing state... [id=prod-fin-observatory/roles/bigquery.dataEditor/serviceAccount:dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_postprocessing_job[0].google_project_iam_member.postprocessing_spanner[0]: Refreshing state... [id=prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_bigquery_reservation_assignment.project_assignment[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/reservations/default/assignments/14420980097257118177]
module.stack.module.spanner[0].google_spanner_instance.main[0]: Refreshing state... [id=prod-fin-observatory/dfo-prod-dc-instance]
google_sql_provision_script.presentation_revoke_public_connect: Refreshing state... [id=prod-fin-observatory/dfo-prod-platform-postgres]
module.stack.google_storage_bucket_iam_member.dataflow_bucket_access[0]: Refreshing state... [id=b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectAdmin/serviceAccount:dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com]
google_sql_provision_script.datasets_revoke_public_connect: Refreshing state... [id=prod-fin-observatory/dfo-prod-platform-postgres]
module.stack.module.ingestion_helper_service.google_storage_bucket_iam_member.helper_bucket_access[0]: Refreshing state... [id=b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectAdmin/serviceAccount:dfo-prod-dc-ing-hlp-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.auth.google_secret_manager_secret_version.maps_api_key_version[0]: Refreshing state... [id=projects/533754688761/secrets/dfo-prod-dc-google-maps-api-key-741a46a2/versions/1]
ephemeral.random_password.presentation_migrator: Closing...
ephemeral.random_password.presentation_migrator: Closing complete after 0s
ephemeral.random_password.datasets_migrator: Closing...
ephemeral.random_password.datasets_migrator: Closing complete after 0s
module.stack.module.ingestion_helper_service.google_cloud_run_v2_service.ingestion_helper[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-ingestion-helper]
module.stack.module.ingestion_preprocessing_job[0].google_cloud_run_v2_job.dc_data_job: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job]
module.stack.module.ingestion_preprocessing_job[0].google_service_account.preprocessing_sa: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_preprocessing_job[0].google_secret_manager_secret_iam_member.preprocessing_secret_accessor["DC_API_KEY"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-dc-api-key/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_preprocessing_job[0].google_secret_manager_secret_iam_member.preprocessing_secret_accessor["MAPS_API_KEY"]: Refreshing state... [id=projects/prod-fin-observatory/secrets/dfo-prod-dc-google-maps-api-key-741a46a2/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_storage_bucket_iam_member.preprocessing_bucket_access[0]: Refreshing state... [id=b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectAdmin/serviceAccount:dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_workflow.google_service_account.workflow_sa[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_service_account.serving_sa: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_service_account_iam_member.workflow_pre_sa_user[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_workflow.google_service_account_iam_member.workflow_act_as_dataflow_sa[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_workflow.google_cloud_run_v2_service_iam_member.helper_invoker[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-ingestion-helper/roles/run.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_project_iam_member.workflow_run_viewer[0]: Refreshing state... [id=prod-fin-observatory/roles/run.viewer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_project_iam_member.workflow_dataflow_developer[0]: Refreshing state... [id=prod-fin-observatory/roles/dataflow.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_project_iam_member.workflow_invoker[0]: Refreshing state... [id=prod-fin-observatory/roles/workflows.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_service_account_iam_member.workflow_post_sa_user[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-pst-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_storage_bucket_iam_member.workflow_bucket_access[0]: Refreshing state... [id=b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectAdmin/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/redis.editor"]: Refreshing state... [id=prod-fin-observatory/roles/redis.editor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/workflows.invoker"]: Refreshing state... [id=prod-fin-observatory/roles/workflows.invoker/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/storage.objectViewer"]: Refreshing state... [id=prod-fin-observatory/roles/storage.objectViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/vpcaccess.user"]: Refreshing state... [id=prod-fin-observatory/roles/vpcaccess.user/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/compute.networkViewer"]: Refreshing state... [id=prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/iam.serviceAccountUser"]: Refreshing state... [id=prod-fin-observatory/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/aiplatform.user"]: Refreshing state... [id=prod-fin-observatory/roles/aiplatform.user/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/secretmanager.secretAccessor"]: Refreshing state... [id=prod-fin-observatory/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/spanner.databaseUser"]: Refreshing state... [id=prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_service_account_iam_member.ingestion_workflow_act_as_serving_sa[0]: Refreshing state... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_spanner_database.database[0]: Refreshing state... [id=dfo-prod-dc-instance/dfo-prod-dc-db]
module.stack.module.spanner[0].google_spanner_database_iam_member.spanner_reader[0]: Refreshing state... [id=prod-fin-observatory/dfo-prod-dc-instance/dfo-prod-dc-db/roles/spanner.databaseUser/serviceAccount:bq-533754688761@bigquery-encryption.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_bigquery_connection.spanner_connection[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/connections/dfo_prod_dc_spanner_connection]
module.stack.module.ingestion_postprocessing_job[0].google_cloud_run_v2_job.dc_postprocessing_job: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-postprocessing-job]
module.stack.google_cloud_run_v2_job_iam_member.workflow_post_developer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-postprocessing-job/roles/run.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_cloud_run_v2_job_iam_member.workflow_post_viewer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-postprocessing-job/roles/run.viewer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_cloud_run_v2_job_iam_member.workflow_post_invoker[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-postprocessing-job/roles/run.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_workflow.google_workflows_workflow.ingestion_orchestrator[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/workflows/dfo-prod-dc-ingestion-workflow]
module.stack.module.datacommons_services[0].google_cloud_run_v2_service.dc_web_service: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-datacommons-service]
module.stack.module.datacommons_services[0].google_cloud_run_v2_service_iam_member.public_access[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-datacommons-service/roles/run.invoker/allUsers]
module.stack.google_cloud_run_v2_service_iam_member.workflow_serving_developer[0]: Refreshing state... [id=projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-datacommons-service/roles/run.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
null_resource.search_api_gemini_key: Refreshing state... [id=3945925123549706418]

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

Terraform will perform the following actions:

  # google_project_iam_member.ingestion_workflow_sa_viewer[0] will be created
  + resource "google_project_iam_member" "ingestion_workflow_sa_viewer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/workflows.viewer"
    }

  # google_project_service.apis["batch.googleapis.com"] will be created
  + resource "google_project_service" "apis" {
      + deletion_policy    = "DELETE"
      + disable_on_destroy = false
      + id                 = (known after apply)
      + project            = "prod-fin-observatory"
      + service            = "batch.googleapis.com"
    }

  # google_project_service.apis["vpcaccess.googleapis.com"] will be destroyed
  # (because key ["vpcaccess.googleapis.com"] is not in for_each map)
  - resource "google_project_service" "apis" {
      - deletion_policy    = "DELETE" -> null
      - disable_on_destroy = false -> null
      - id                 = "prod-fin-observatory/vpcaccess.googleapis.com" -> null
      - project            = "prod-fin-observatory" -> null
      - service            = "vpcaccess.googleapis.com" -> null
    }

  # google_secret_manager_secret_iam_member.serving_sa_gemini_key will be created
  + resource "google_secret_manager_secret_iam_member" "serving_sa_gemini_key" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = "prod-fin-observatory"
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "dfo-prod-gemini-api-key"
    }

  # null_resource.search_api_gemini_key must be replaced
-/+ resource "null_resource" "search_api_gemini_key" {
      ~ id       = "3945925123549706418" -> (known after apply)
      ~ triggers = { # forces replacement
          ~ "always_run" = "2026-10-15T20:53:36Z" -> (known after apply)
        }
    }

  # module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0] will be destroyed
  # (because google_cloud_run_v2_job_iam_member.workflow_pre_developer is not in configuration)
  - resource "google_cloud_run_v2_job_iam_member" "workflow_pre_developer" {
      - etag     = "BwZdF2CqKZE=" -> null
      - id       = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - location = "europe-west1" -> null
      - member   = "serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - name     = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job" -> null
      - project  = "prod-fin-observatory" -> null
      - role     = "roles/run.developer" -> null
    }

  # module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_invoker[0] will be destroyed
  # (because google_cloud_run_v2_job_iam_member.workflow_pre_invoker is not in configuration)
  - resource "google_cloud_run_v2_job_iam_member" "workflow_pre_invoker" {
      - etag     = "BwZdF2CqKZE=" -> null
      - id       = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - location = "europe-west1" -> null
      - member   = "serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - name     = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job" -> null
      - project  = "prod-fin-observatory" -> null
      - role     = "roles/run.invoker" -> null
    }

  # module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_viewer[0] will be destroyed
  # (because google_cloud_run_v2_job_iam_member.workflow_pre_viewer is not in configuration)
  - resource "google_cloud_run_v2_job_iam_member" "workflow_pre_viewer" {
      - etag     = "BwZdF2CqKZE=" -> null
      - id       = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.viewer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - location = "europe-west1" -> null
      - member   = "serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - name     = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job" -> null
      - project  = "prod-fin-observatory" -> null
      - role     = "roles/run.viewer" -> null
    }

  # module.stack.google_project_iam_member.workflow_batch_editor[0] will be created
  + resource "google_project_iam_member" "workflow_batch_editor" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/batch.jobsEditor"
    }

  # module.stack.google_storage_bucket_iam_member.serving_bucket_access[0] will be created
  + resource "google_storage_bucket_iam_member" "serving_bucket_access" {
      + bucket = "dfo-prod-dc-artifacts-prod-fin-observatory"
      + etag   = (known after apply)
      + id     = (known after apply)
      + member = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + role   = "roles/storage.objectViewer"
    }

  # module.stack.terraform_data.redis_network_validation will be created
  + resource "terraform_data" "redis_network_validation" {
      + id = (known after apply)
    }

  # module.stack.terraform_data.worker_subnet_validation will be created
  + resource "terraform_data" "worker_subnet_validation" {
      + id = (known after apply)
    }

  # module.stack.module.datacommons_services[0].google_cloud_run_v2_service.dc_web_service will be updated in-place
  ~ resource "google_cloud_run_v2_service" "dc_web_service" {
        id                      = "projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-datacommons-service"
        name                    = "dfo-prod-dc-datacommons-service"
        # (36 unchanged attributes hidden)

      ~ template {
            # (11 unchanged attributes hidden)

          ~ containers {
                name             = null
                # (8 unchanged attributes hidden)

              - env {
                  - name  = "GEMINI_API_KEY" -> null
                    # (1 unchanged attribute hidden)

                  - value_source {
                      - secret_key_ref {
                          - secret  = "projects/prod-fin-observatory/secrets/dfo-prod-gemini-api-key" -> null
                          - version = "latest" -> null
                        }
                    }
                }
              - env {
                  - name  = "TEMP_LOCATION" -> null
                  - value = "gs://dfo-prod-dc-artifacts-prod-fin-observatory/ingestion/internal/temp" -> null
                }
              - env {
                  - name  = "USE_SPANNER_GRAPH" -> null
                  - value = "true" -> null
                }
              + env {
                  + name  = "REDIS_CA_CERT"
                    # (1 unchanged attribute hidden)
                }
              + env {
                  + name  = "TEMP_LOCATION"
                  + value = "DEPRECATED_UNUSED"
                }

                # (25 unchanged blocks hidden)
            }

            # (1 unchanged block hidden)
        }

        # (2 unchanged blocks hidden)
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/compute.networkViewer"] will be destroyed
  # (because key ["roles/compute.networkViewer"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/compute.networkViewer" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/iam.serviceAccountUser"] will be destroyed
  # (because key ["roles/iam.serviceAccountUser"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/iam.serviceAccountUser" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/redis.editor"] will be destroyed
  # (because key ["roles/redis.editor"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/redis.editor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/redis.editor" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/secretmanager.secretAccessor"] will be destroyed
  # (because key ["roles/secretmanager.secretAccessor"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/secretmanager.secretAccessor" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/spanner.databaseReader"] will be created
  + resource "google_project_iam_member" "serving_sa_roles" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/spanner.databaseReader"
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/spanner.databaseUser"] will be destroyed
  # (because key ["roles/spanner.databaseUser"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/spanner.databaseUser" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/storage.objectViewer"] will be destroyed
  # (because key ["roles/storage.objectViewer"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/storage.objectViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/storage.objectViewer" -> null
    }

  # module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/workflows.invoker"] will be destroyed
  # (because key ["roles/workflows.invoker"] is not in for_each map)
  - resource "google_project_iam_member" "serving_sa_roles" {
      - etag    = "BwZehhjB2XA=" -> null
      - id      = "prod-fin-observatory/roles/workflows.invoker/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - member  = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - project = "prod-fin-observatory" -> null
      - role    = "roles/workflows.invoker" -> null
    }

  # module.stack.module.datacommons_services[0].google_secret_manager_secret_iam_member.serving_secret_accessor["DC_API_KEY"] will be created
  + resource "google_secret_manager_secret_iam_member" "serving_secret_accessor" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = "prod-fin-observatory"
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "projects/prod-fin-observatory/secrets/dfo-prod-dc-api-key"
    }

  # module.stack.module.datacommons_services[0].google_secret_manager_secret_iam_member.serving_secret_accessor["MAPS_API_KEY"] will be created
  + resource "google_secret_manager_secret_iam_member" "serving_secret_accessor" {
      + etag      = (known after apply)
      + id        = (known after apply)
      + member    = "serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project   = "prod-fin-observatory"
      + role      = "roles/secretmanager.secretAccessor"
      + secret_id = "projects/prod-fin-observatory/secrets/dfo-prod-dc-google-maps-api-key-741a46a2"
    }

  # module.stack.module.ingestion_dataflow.data.google_project.project will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "google_project" "project" {
      + auto_create_network = (known after apply)
      + billing_account     = (known after apply)
      + deletion_policy     = (known after apply)
      + effective_labels    = (known after apply)
      + folder_id           = (known after apply)
      + id                  = (known after apply)
      + labels              = (known after apply)
      + name                = (known after apply)
      + number              = (known after apply)
      + org_id              = (known after apply)
      + project_id          = "prod-fin-observatory"
      + tags                = (known after apply)
      + terraform_labels    = (known after apply)
    }

  # module.stack.module.ingestion_dataflow.google_service_account_iam_member.workflows_token_creator[0] must be replaced
-/+ resource "google_service_account_iam_member" "workflows_token_creator" {
      ~ etag               = "BwZdF2mOlZk=" -> (known after apply)
      ~ id                 = "projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/serviceAccount:service-533754688761@gcp-sa-workflows.iam.gserviceaccount.com" -> (known after apply)
      ~ member             = "serviceAccount:service-533754688761@gcp-sa-workflows.iam.gserviceaccount.com" -> (known after apply) # forces replacement
        # (2 unchanged attributes hidden)
    }

  # module.stack.module.ingestion_helper_service.google_cloud_run_v2_service.ingestion_helper[0] will be updated in-place
  ~ resource "google_cloud_run_v2_service" "ingestion_helper" {
        id                      = "projects/prod-fin-observatory/locations/europe-west1/services/dfo-prod-dc-ingestion-helper"
      ~ ingress                 = "INGRESS_TRAFFIC_ALL" -> "INGRESS_TRAFFIC_INTERNAL_ONLY"
        name                    = "dfo-prod-dc-ingestion-helper"
        # (35 unchanged attributes hidden)

      ~ template {
            # (11 unchanged attributes hidden)

          ~ containers {
              ~ image            = "gcr.io/datcom-ci/datacommons-ingestion-helper:1.1.5" -> "gcr.io/datcom-ci/datacommons-ingestion-helper:1.1.6"
                name             = null
                # (7 unchanged attributes hidden)

              + env {
                  + name  = "REDIS_CA_CERT"
                    # (1 unchanged attribute hidden)
                }

                # (17 unchanged blocks hidden)
            }
        }

        # (2 unchanged blocks hidden)
    }

  # module.stack.module.ingestion_postprocessing_job[0].google_cloud_run_v2_job.dc_postprocessing_job will be updated in-place
  ~ resource "google_cloud_run_v2_job" "dc_postprocessing_job" {
        id                       = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-postprocessing-job"
        name                     = "dfo-prod-dc-ingestion-postprocessing-job"
        # (29 unchanged attributes hidden)

      ~ template {
            # (4 unchanged attributes hidden)

          ~ template {
                # (6 unchanged attributes hidden)

              ~ containers {
                  ~ image       = "gcr.io/datcom-ci/datacommons-aggregation-helper:1.1.5" -> "gcr.io/datcom-ci/datacommons-aggregation-helper:1.1.6"
                    name        = null
                    # (4 unchanged attributes hidden)

                  - env {
                      - name  = "TEMP_LOCATION" -> null
                      - value = "gs://dfo-prod-dc-artifacts-prod-fin-observatory/ingestion/internal/temp" -> null
                    }
                  - env {
                      - name  = "USE_SPANNER_GRAPH" -> null
                      - value = "true" -> null
                    }
                  + env {
                      + name  = "REDIS_CA_CERT"
                        # (1 unchanged attribute hidden)
                    }
                  + env {
                      + name  = "TEMP_LOCATION"
                      + value = "DEPRECATED_UNUSED"
                    }

                    # (18 unchanged blocks hidden)
                }
            }
        }
    }

  # module.stack.module.ingestion_preprocessing_job[0].google_cloud_run_v2_job.dc_data_job will be destroyed
  # (because google_cloud_run_v2_job.dc_data_job is not in configuration)
  - resource "google_cloud_run_v2_job" "dc_data_job" {
      - annotations              = {} -> null
      - conditions               = [] -> null
      - create_time              = "2026-10-05T12:52:49.625219Z" -> null
      - creator                  = "dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - deletion_policy          = "DELETE" -> null
      - deletion_protection      = true -> null
      - effective_annotations    = {} -> null
      - effective_labels         = {
          - "goog-terraform-provisioned" = "true"
        } -> null
      - etag                     = "\"CKG7jtYGELirkKoC/cHJvamVjdHMvcHJvZC1maW4tb2JzZXJ2YXRvcnkvbG9jYXRpb25zL2V1cm9wZS13ZXN0MS9qb2JzL2Rmby1wcm9kLWRjLWluZ2VzdGlvbi1wcmVwcm9jZXNzaW5nLWpvYg\"" -> null
      - execution_count          = 31 -> null
      - generation               = "1" -> null
      - id                       = "projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job" -> null
      - labels                   = {} -> null
      - last_modifier            = "dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com" -> null
      - latest_created_execution = [
          - {
              - completion_time = "2026-10-15T16:17:38.131031Z"
              - create_time     = "2026-10-15T16:13:10.325720Z"
              - name            = "dfo-prod-dc-ingestion-preprocessing-job-hq7xr"
            },
        ] -> null
      - launch_stage             = "GA" -> null
      - location                 = "europe-west1" -> null
      - name                     = "dfo-prod-dc-ingestion-preprocessing-job" -> null
      - observed_generation      = "1" -> null
      - project                  = "prod-fin-observatory" -> null
      - reconciling              = false -> null
      - terminal_condition       = [
          - {
              - state                = "CONDITION_SUCCEEDED"
              - type                 = "Ready"
                # (6 unchanged attributes hidden)
            },
        ] -> null
      - terraform_labels         = {
          - "goog-terraform-provisioned" = "true"
        } -> null
      - uid                      = "033f9860-62b1-424a-bd2e-112615e4e02c" -> null
      - update_time              = "2026-10-05T12:52:49.625219Z" -> null
        # (6 unchanged attributes hidden)

      - template {
          - annotations = {} -> null
          - labels      = {} -> null
          - parallelism = 0 -> null
          - task_count  = 1 -> null

          - template {
              - execution_environment         = "EXECUTION_ENVIRONMENT_GEN2" -> null
              - gpu_zonal_redundancy_disabled = false -> null
              - max_retries                   = 0 -> null
              - service_account               = "dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com" -> null
              - timeout                       = "21600s" -> null
                # (1 unchanged attribute hidden)

              - containers {
                  - args        = [] -> null
                  - command     = [] -> null
                  - depends_on  = [] -> null
                  - image       = "gcr.io/datcom-ci/datacommons-data:1.1.5" -> null
                    name        = null
                    # (1 unchanged attribute hidden)

                  - env {
                      - name  = "DC_API_KEY" -> null
                        # (1 unchanged attribute hidden)

                      - value_source {
                          - secret_key_ref {
                              - secret  = "projects/prod-fin-observatory/secrets/dfo-prod-dc-api-key" -> null
                              - version = "latest" -> null
                            }
                        }
                    }
                  - env {
                      - name  = "ENABLE_SPANNER_EMBEDDINGS" -> null
                      - value = "true" -> null
                    }
                  - env {
                      - name  = "FORCE_RESTART" -> null
                        # (1 unchanged attribute hidden)
                    }
                  - env {
                      - name  = "GCP_SPANNER_DATABASE_NAME" -> null
                      - value = "dfo-prod-dc-db" -> null
                    }
                  - env {
                      - name  = "GCP_SPANNER_INSTANCE_ID" -> null
                      - value = "dfo-prod-dc-instance" -> null
                    }
                  - env {
                      - name  = "GCS_BUCKET" -> null
                      - value = "dfo-prod-dc-artifacts-prod-fin-observatory" -> null
                    }
                  - env {
                      - name  = "GCS_INPUT_FOLDER" -> null
                      - value = "ingestion/input" -> null
                    }
                  - env {
                      - name  = "GCS_OUTPUT_FOLDER" -> null
                      - value = "ingestion/internal" -> null
                    }
                  - env {
                      - name  = "IMPORT_PROXY_ENTITIES" -> null
                      - value = "false" -> null
                    }
                  - env {
                      - name  = "INPUT_DIR" -> null
                      - value = "gs://dfo-prod-dc-artifacts-prod-fin-observatory/ingestion/input" -> null
                    }
                  - env {
                      - name  = "MAPS_API_KEY" -> null
                        # (1 unchanged attribute hidden)

                      - value_source {
                          - secret_key_ref {
                              - secret  = "projects/prod-fin-observatory/secrets/dfo-prod-dc-google-maps-api-key-741a46a2" -> null
                              - version = "latest" -> null
                            }
                        }
                    }
                  - env {
                      - name  = "OUTPUT_DIR" -> null
                      - value = "gs://dfo-prod-dc-artifacts-prod-fin-observatory/ingestion/internal" -> null
                    }
                  - env {
                      - name  = "PROJECT_ID" -> null
                      - value = "prod-fin-observatory" -> null
                    }
                  - env {
                      - name  = "REDIS_HOST" -> null
                        # (1 unchanged attribute hidden)
                    }
                  - env {
                      - name  = "REDIS_PORT" -> null
                        # (1 unchanged attribute hidden)
                    }
                  - env {
                      - name  = "REGION" -> null
                      - value = "europe-west1" -> null
                    }
                  - env {
                      - name  = "TEMP_LOCATION" -> null
                      - value = "gs://dfo-prod-dc-artifacts-prod-fin-observatory/ingestion/internal/temp" -> null
                    }
                  - env {
                      - name  = "USE_CLOUDSQL" -> null
                      - value = "false" -> null
                    }
                  - env {
                      - name  = "USE_SPANNER_GRAPH" -> null
                      - value = "true" -> null
                    }
                  - env {
                      - name  = "WORKFLOW_LOCATION" -> null
                      - value = "europe-west1" -> null
                    }

                  - resources {
                      - limits = {
                          - "cpu"    = "8"
                          - "memory" = "32G"
                        } -> null
                    }
                }
            }
        }
    }

  # module.stack.module.ingestion_preprocessing_job[0].google_project_iam_member.preprocessing_batch_agent will be created
  + resource "google_project_iam_member" "preprocessing_batch_agent" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/batch.agentReporter"
    }

  # module.stack.module.ingestion_preprocessing_job[0].google_project_iam_member.preprocessing_log_writer will be created
  + resource "google_project_iam_member" "preprocessing_log_writer" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:dfo-prod-dc-ing-pre-sa@prod-fin-observatory.iam.gserviceaccount.com"
      + project = "prod-fin-observatory"
      + role    = "roles/logging.logWriter"
    }

  # module.stack.module.ingestion_workflow.google_workflows_workflow.ingestion_orchestrator[0] will be updated in-place
  ~ resource "google_workflows_workflow" "ingestion_orchestrator" {
        id                      = "projects/prod-fin-observatory/locations/europe-west1/workflows/dfo-prod-dc-ingestion-workflow"
        name                    = "dfo-prod-dc-ingestion-workflow"
      ~ source_contents         = <<-EOT
            main:
              params: [input]
              steps:
                - init:
                    assign:
                      - project_id: 'prod-fin-observatory'
          +           - region: 'europe-west1'
          +           - bucket_name: 'dfo-prod-dc-artifacts-prod-fin-observatory'
          +           - temp_path_prefix: 'ingestion/internal/temp'
          +           - temp_gcs_uri: '${"gs://" + bucket_name + "/" + temp_path_prefix}'
                      - workflow_id: '${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}'
                      - version: '${"version-" + string(int(sys.now()))}'
          -           - bucket_name: '${text.split(input.tempLocation, "/")[2]}'
          -           - temp_path_prefix: '${text.replace_all(input.tempLocation, "gs://" + bucket_name + "/", "")}'
                      - execution_error: null
                      - postprocessing_result: null
                      - embedding_result: null
                      - current_stage: "dataflow"
                      - job_id: null
                      - lock_timeout: 82800
                      - lock_retries: 0
                      - max_lock_retries: ${int(lock_timeout / 120)}
                      - run_embeddings: true
                      - run_postproc: true
                      - generate_stat_var_groups: false
                      - decoded_imports: []
                      - num_imports: 0
                      - combined_import_name: ""
          -           - prep_job_name: 'dfo-prod-dc-ingestion-preprocessing-job'
                      - postproc_job_name: 'dfo-prod-dc-ingestion-postprocessing-job'
                      - comma_separated_imports: ""
                      - provenances_list: []
                      - imports_history_list: []
                      - imports_history_str: ""
          +           - t_pre_timestamp: null
          +           - rollback_failed: false
                      - launch_params:
                          projectId: '${project_id}'
          -               spannerInstanceId: '${default(map.get(input, "spannerInstanceId"), "")}'
          -               spannerDatabaseId: '${default(map.get(input, "spannerDatabaseId"), "")}'
          +               spannerInstanceId: 'dfo-prod-dc-instance'
          +               spannerDatabaseId: 'dfo-prod-dc-db'
                          importList: '${default(map.get(input, "importList"), "")}'
          -               tempLocation: '${input.tempLocation}'
          -               stagingLocation: '${input.tempLocation}'
          +               tempLocation: '${temp_gcs_uri}'
          +               stagingLocation: '${temp_gcs_uri}'
                          forceCombineNodes: 'true'
                          isBaseDc: 'false'
                - normalize_imports:
                    switch:
                      - condition: '${default(map.get(input, "importList"), "") != ""}'
                        assign:
                          - decoded_imports: '${json.decode(input.importList)}'
                      - condition: '${len(default(map.get(input, "imports"), [])) > 0}'
                        steps:
                          - init_decoded:
                              assign:
                                - decoded_imports: []
                                - imports_json_str: ""
                          - build_decoded_loop:
                              for:
                                value: imp_str
                                in: '${input.imports}'
                                steps:
                                  - add_to_decoded:
                                      assign:
                                        - imports_json_str: '${imports_json_str + ",{\"importName\":\"" + imp_str + "\",\"graphPath\":\"\"}"}'
                          - decode_imports:
                              assign:
                                - decoded_imports: '${json.decode("[" + text.substring(imports_json_str, 1, len(imports_json_str)) + "]")}'
                      - condition: true
                        assign:
                          - decoded_imports: []
                - set_num_imports:
                    assign:
                      - num_imports: '${len(decoded_imports)}'
                - build_lists:
                    for:
                      value: imp
                      in: ${decoded_imports}
                      steps:
                        - append_lists:
                            assign:
                              - history_item_str: '${",{\"importName\":\"" + imp.importName + "\",\"latestVersion\":\"" + version + "\"}"}'
                              - imports_history_str: '${imports_history_str + history_item_str}'
                              - clean_item: '${text.replace_all(text.replace_all(text.to_lower(imp.importName), "/", "-"), "_", "-")}'
                              - join_prefix: '${if(combined_import_name == "", "", "-")}'
                              - combined_import_name: '${combined_import_name + join_prefix + clean_item}'
                              - comma_separated_imports: '${if(comma_separated_imports == "", imp.importName, comma_separated_imports + "," + imp.importName)}'
                - decode_lists:
                    assign:
                      - imports_history_list: '${json.decode("[" + text.substring(imports_history_str, 1, len(imports_history_str)) + "]")}'
                - set_dataflow_job_name:
                    assign:
                      - import_name_len: '${len(combined_import_name)}'
                      - substring_end: '${if(import_name_len < 35, import_name_len, 35)}'
                      - sanitized_short_import: '${text.substring(combined_import_name, 0, substring_end)}'
                      - dataflow_job_name: '${"dfo-prod-" + sanitized_short_import + "-" + string(int(sys.now()))}'
          -     
          + 
                - run_preprocessing:
                    call: launch_and_poll_preprocessing_job
                    args:
          -           job_name: '${prep_job_name}'
                      workflow_id: '${workflow_id}'
          -           temp_location: '${input.tempLocation}'
          +           temp_gcs_uri: '${temp_gcs_uri}'
                      imports_arg: '${comma_separated_imports}'
          -           region: '${input.region}'
          +           region: '${region}'
                      project_id: 'prod-fin-observatory'
                    result: prep_res
            
                - read_handshake_file:
                    call: googleapis.storage.v1.objects.get
                    args:
                      bucket: '${bucket_name}'
                      object: '${text.url_encode(temp_path_prefix + "/datacommons/ingestion_records/" + workflow_id + ".json")}'
                      alt: 'media'
                    result: handshake_data
            
                - update_launch_params:
                    assign:
                      - launch_params.importList: '${handshake_data.importList}'
                      - generate_stat_var_groups: '${default(map.get(handshake_data, "generateStatVarGroups"), false)}'
                      - decoded_imports: '${json.decode(handshake_data.importList)}'
                      - provenances_list: []
                - extract_provenance_dcids:
                    for:
                      value: item
                      in: ${decoded_imports}
                      steps:
                        - append_provenance:
                            assign:
                              - provenances_list: '${list.concat(provenances_list, item.importName)}'
            
            
                - try_acquire_lock:
                    try:
                      call: http.post
                      args:
                        url: 'https://dfo-prod-dc-ingestion-helper-2qrxytrsda-ew.a.run.app/database/lock/acquire'
                        auth:
                          type: OIDC
                        body:
                          workflowId: '${workflow_id}'
                          timeout: '${lock_timeout}'
                      result: lock_result
                    except:
                      as: e
                      steps:
                        - handle_lock_busy:
                            switch:
                              - condition: '${default(map.get(e, "code"), 0) == 503 and lock_retries < max_lock_retries}'
                                next: increment_retries_and_wait
                        - unhandled_error:
                            raise: ${e}
                - lock_acquired_success:
          +         assign:
          +           - t_pre_timestamp: '${time.format(sys.now())}'
                    next: update_history_pending
                - increment_retries_and_wait:
                    assign:
                      - lock_retries: ${lock_retries + 1}
                - wait_for_lock:
                    call: sys.sleep
                    args:
                      seconds: 120
                    next: try_acquire_lock
            
                - update_history_pending:
                    call: update_history
                    args:
                      workflow_id: '${workflow_id}'
                      status: 'PENDING'
                      stage: 'dataflow'
                      job_id: null
                      import_list: '${imports_history_list}'
            
                - process_ingestion:
                    try:
                      steps:
                        - launch_dataflow:
                            call: launch_and_poll_dataflow
                            args:
                              job_name: '${dataflow_job_name}'
                              launch_params: '${launch_params}'
          -                   temp_location: '${input.tempLocation}'
          -                   region: '${input.region}'
          +                   temp_gcs_uri: '${temp_gcs_uri}'
          +                   region: '${region}'
                              workflow_id: '${workflow_id}'
          +                   template_path: 'gs://datcom-templates/templates/flex/ingestion-1.1.6.json'
          +                   stage: 'dataflow'
                            result: dataflow_res
          -             
          + 
                        - assign_job_id:
                            assign:
                              - job_id: '${dataflow_res.job_id}'
                              - launch_result: '${dataflow_res.launch_result}'
            
                        - set_stage_postproc:
                            assign:
                              - current_stage: "postprocessing"
            
                        - update_history_postproc_running:
                            call: update_history
                            args:
                              workflow_id: '${workflow_id}'
                              status: 'RUNNING'
                              stage: 'postprocessing'
                              job_id: null
                              import_list: null
            
                        - run_postprocessing_parallel:
                            parallel:
                              shared: [postprocessing_result, embedding_result]
                              branches:
                                - postprocessing_branch:
                                    steps:
                                      - call_postproc:
                                          call: run_postprocessing_job
                                          args:
                                            run_flag: '${run_postproc}'
                                            import_list: '${provenances_list}'
                                            job_name: '${postproc_job_name}'
          -                                 region: '${input.region}'
          +                                 region: '${region}'
                                            project_id: '${project_id}'
                                            workflow_id: '${workflow_id}'
                                            generate_stat_var_groups: '${generate_stat_var_groups}'
                                          result: postprocessing_result
                                - embeddings_branch:
                                    steps:
                                      - call_embeddings:
                                          call: run_embeddings_job
                                          args:
                                            run_flag: '${run_embeddings}'
                                          result: embedding_result
            
                        - update_ingestion_status_success:
                            call: update_ingestion_status
                            args:
                              workflow_id: '${workflow_id}'
                              job_id: '${job_id}'
                              status: 'SUCCESS'
                              import_list: '${imports_history_list}'
            
                        - update_history_postproc_success:
                            call: update_history
                            args:
                              workflow_id: '${workflow_id}'
                              status: 'SUCCESS'
                              stage: null
                              job_id: null
                              import_list: null
            
                    except:
                      as: e
                      steps:
          -             - update_history_failure:
          +             - extract_error_job_id:
          +                 try:
          +                   assign:
          +                     - job_id: '${default(map.get(e, "job_id"), job_id)}'
          +                 except:
          +                   as: _map_err
          +                   assign:
          +                     - job_id: '${job_id}'
          +             - check_should_rollback:
          +                 switch:
          +                   - condition: '${job_id != null}'
          +                     next: update_history_rollback_starting
          +                 next: update_history_no_rollback
          +             - update_history_no_rol

… truncated — full plan in the job summary.

Stack dcp · b52ff45 · @jm-rivera · run

….1.6

feat(dcp): move the dcp stack to Data Commons Platform 1.1.6
@jm-rivera
jm-rivera merged commit a19bafe into main Oct 23, 2026
14 checks passed
@github-actions

Copy link
Copy Markdown

Terraform Apply — foundation

Apply complete! Resources: 16 added, 0 changed, 2 destroyed.

Init Validate Apply
pass pass pass
Show apply output
Acquiring state lock. This may take a few moments...
module.applier.google_project_iam_member.project_roles["roles/compute.networkViewer"]: Destroying... [id=prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
module.applier.google_project_iam_member.project_roles["roles/vpcaccess.admin"]: Destroying... [id=prod-fin-observatory/roles/vpcaccess.admin/serviceAccount:dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com]
google_service_account_iam_member.ingestion_workflow_token_creator["prod-ingestion"]: Creating...
google_spanner_database_iam_member.ingestion_database_reader["prod-ingestion"]: Creating...
google_project_iam_member.ingestion_workflow_invoker["prod-ingestion"]: Creating...
google_storage_bucket_iam_member.ingestion_artifacts_writer["prod-ingestion"]: Creating...
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-foundation-principals"]: Creating...
google_project_iam_member.ingestion_viewer["prod-ingestion roles/run.viewer"]: Creating...
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-ai-principals"]: Creating...
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-telemetry-principals"]: Creating...
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-foundation-principals"]: Creation complete after 4s [id=projects/prod-fin-observatory/secrets/dfo-prod-foundation-principals/roles/secretmanager.secretAccessor/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-ai-principals"]: Creation complete after 4s [id=projects/prod-fin-observatory/secrets/dfo-prod-ai-principals/roles/secretmanager.secretAccessor/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/serviceusage.serviceUsageConsumer"]: Creating...
google_project_iam_member.ingestion_viewer["prod-ingestion roles/spanner.viewer"]: Creating...
google_secret_manager_secret_iam_member.principals_planner["dfo-prod-telemetry-principals"]: Creation complete after 4s [id=projects/prod-fin-observatory/secrets/dfo-prod-telemetry-principals/roles/secretmanager.secretAccessor/serviceAccount:dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/workflows.viewer"]: Creating...
google_service_account_iam_member.ingestion_workflow_token_creator["prod-ingestion"]: Creation complete after 5s [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/logging.viewer"]: Creating...
google_spanner_database_iam_member.ingestion_database_reader["prod-ingestion"]: Creation complete after 6s [id=prod-fin-observatory/dfo-prod-dc-instance/dfo-prod-dc-db/roles/spanner.databaseReader/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/dataflow.viewer"]: Creating...
google_storage_bucket_iam_member.ingestion_artifacts_writer["prod-ingestion"]: Creation complete after 6s [id=b/dfo-prod-dc-artifacts-prod-fin-observatory/roles/storage.objectUser/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/monitoring.viewer"]: Creating...
google_project_iam_member.ingestion_viewer["prod-ingestion roles/run.viewer"]: Creation complete after 8s [id=prod-fin-observatory/roles/run.viewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/batch.jobsViewer"]: Creating...
google_project_iam_member.ingestion_workflow_invoker["prod-ingestion"]: Creation complete after 8s [id=prod-fin-observatory/roles/workflows.invoker/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/storage.bucketViewer"]: Creating...
module.applier.google_project_iam_member.project_roles["roles/compute.networkViewer"]: Destruction complete after 8s
module.applier.google_project_iam_member.project_roles["roles/vpcaccess.admin"]: Still destroying... [id=prod-fin-observatory/roles/vpcaccess.ad...in-observatory.iam.gserviceaccount.com, 00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/monitoring.viewer"]: Creation complete after 7s [id=prod-fin-observatory/roles/monitoring.viewer/***]
module.applier.google_project_iam_member.project_roles["roles/vpcaccess.admin"]: Destruction complete after 14s
google_project_iam_member.ingestion_viewer["prod-ingestion roles/serviceusage.serviceUsageConsumer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/spanner.viewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/workflows.viewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/logging.viewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/dataflow.viewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/batch.jobsViewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/logging.viewer"]: Creation complete after 13s [id=prod-fin-observatory/roles/logging.viewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/spanner.viewer"]: Creation complete after 14s [id=prod-fin-observatory/roles/spanner.viewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/storage.bucketViewer"]: Still creating... [00m10s elapsed]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/serviceusage.serviceUsageConsumer"]: Creation complete after 14s [id=prod-fin-observatory/roles/serviceusage.serviceUsageConsumer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/dataflow.viewer"]: Creation complete after 13s [id=prod-fin-observatory/roles/dataflow.viewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/workflows.viewer"]: Creation complete after 15s [id=prod-fin-observatory/roles/workflows.viewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/storage.bucketViewer"]: Creation complete after 11s [id=prod-fin-observatory/roles/storage.bucketViewer/***]
google_project_iam_member.ingestion_viewer["prod-ingestion roles/batch.jobsViewer"]: Creation complete after 11s [id=prod-fin-observatory/roles/batch.jobsViewer/***]

Apply complete! Resources: 16 added, 0 changed, 2 destroyed.

Outputs:

ai_deployer_service_account = "dfo-ai-deployer@prod-fin-observatory.iam.gserviceaccount.com"
apis_deployer_service_account = "dfo-apis-deployer@prod-fin-observatory.iam.gserviceaccount.com"
applier_service_account = "dfo-infra-applier@prod-fin-observatory.iam.gserviceaccount.com"
artifact_registry_datacommons_repository_id = "datacommons"
artifact_registry_dcp_build_cache_repository_id = "dfo-dcp-build-cache"
artifact_registry_website_repository_id = "dfo-website"
dcp_deployer_service_account = "dfo-dcp-deployer@prod-fin-observatory.iam.gserviceaccount.com"
docs_sync_service_account = "dfo-docs-sync@prod-fin-observatory.iam.gserviceaccount.com"
planner_service_account = "dfo-infra-planner@prod-fin-observatory.iam.gserviceaccount.com"
project_id = "prod-fin-observatory"
region = "europe-west1"
website_deployer_service_account = "dfo-website-deployer@prod-fin-observatory.iam.gserviceaccount.com"
workload_identity_pool_id = "github-pool"
workload_identity_provider = "projects/533754688761/locations/global/workloadIdentityPools/github-pool/providers/github"

Stack foundation · a19bafe · @jm-rivera · run

@github-actions

Copy link
Copy Markdown

Terraform Apply — ai

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Init Validate Apply
pass pass pass
Show apply output
Acquiring state lock. This may take a few moments...
ephemeral.random_password.mcp_api_token: Opening...
ephemeral.random_password.studio_api_token: Opening...
ephemeral.random_password.studio_api_token: Opening complete after 0s
ephemeral.random_password.mcp_api_token: Opening complete after 0s
ephemeral.random_password.mcp_api_token: Closing...
ephemeral.random_password.studio_api_token: Closing...
ephemeral.random_password.studio_api_token: Closing complete after 0s
ephemeral.random_password.mcp_api_token: Closing complete after 0s

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

langfuse_export_job_name = "dfo-prod-langfuse-export"
runtime_service_account_email = "dfo-prod-ai-run@prod-fin-observatory.iam.gserviceaccount.com"
service_name = "dfo-prod-ai"
service_url = "https://dfo-prod-ai-2qrxytrsda-ew.a.run.app"
studio_api_token_secret = "dfo-prod-studio-api-token"

Stack ai · a19bafe · @jm-rivera · run

@github-actions

Copy link
Copy Markdown

Terraform Apply — dcp

Apply failed. See details below.

Init Validate Apply
pass pass fail

Output:

Acquiring state lock. This may take a few moments...
null_resource.search_api_gemini_key: Destroying... [id=3945925123549706418]
ephemeral.random_password.presentation_migrator: Opening...
null_resource.search_api_gemini_key: Destruction complete after 0s
ephemeral.random_password.datasets_migrator: Opening...
ephemeral.random_password.datasets_migrator: Opening complete after 0s
ephemeral.random_password.presentation_migrator: Opening complete after 0s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_viewer[0]: Destroying... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.viewer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/storage.objectViewer"]: Destroying... [id=prod-fin-observatory/roles/storage.objectViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_dataflow.google_service_account_iam_member.workflows_token_creator[0]: Destroying... [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-dc-ing-df-sa@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/serviceAccount:service-533754688761@gcp-sa-workflows.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/redis.editor"]: Destroying... [id=prod-fin-observatory/roles/redis.editor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0]: Destroying... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.developer/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_project_iam_member.bq_sa_spanner_viewer[0]: Destroying... [id=prod-fin-observatory/roles/spanner.viewer/serviceAccount:bq-533754688761@bigquery-encryption.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/iam.serviceAccountUser"]: Destroying... [id=prod-fin-observatory/roles/iam.serviceAccountUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/workflows.invoker"]: Destroying... [id=prod-fin-observatory/roles/workflows.invoker/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_spanner_database_iam_member.spanner_reader[0]: Destroying... [id=prod-fin-observatory/dfo-prod-dc-instance/dfo-prod-dc-db/roles/spanner.databaseUser/serviceAccount:bq-533754688761@bigquery-encryption.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/spanner.databaseUser"]: Destroying... [id=prod-fin-observatory/roles/spanner.databaseUser/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.ingestion_dataflow.google_service_account_iam_member.workflows_token_creator[0]: Destruction complete after 4s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_invoker[0]: Destroying... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job/roles/run.invoker/serviceAccount:dfo-prod-dc-ing-wf-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_spanner_database_iam_member.spanner_reader[0]: Destruction complete after 6s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/secretmanager.secretAccessor"]: Destroying... [id=prod-fin-observatory/roles/secretmanager.secretAccessor/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/redis.editor"]: Destruction complete after 8s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/compute.networkViewer"]: Destroying... [id=prod-fin-observatory/roles/compute.networkViewer/serviceAccount:dfo-prod-dc-srvs-sa@prod-fin-observatory.iam.gserviceaccount.com]
module.stack.module.spanner[0].google_project_iam_member.bq_sa_spanner_viewer[0]: Destruction complete after 8s
ephemeral.random_password.datasets_migrator: Closing...
ephemeral.random_password.datasets_migrator: Closing complete after 0s
ephemeral.random_password.presentation_migrator: Closing...
ephemeral.random_password.presentation_migrator: Closing complete after 0s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/workflows.invoker"]: Destruction complete after 8s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/iam.serviceAccountUser"]: Destruction complete after 8s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_viewer[0]: Destruction complete after 8s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/storage.objectViewer"]: Destruction complete after 9s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/spanner.databaseUser"]: Destruction complete after 9s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0]: Still destroying... [id=projects/prod-fin-observatory/locations...in-observatory.iam.gserviceaccount.com, 00m10s elapsed]
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/compute.networkViewer"]: Destruction complete after 6s
module.stack.module.datacommons_services[0].google_project_iam_member.serving_sa_roles["roles/secretmanager.secretAccessor"]: Destruction complete after 8s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_invoker[0]: Still destroying... [id=projects/prod-fin-observatory/locations...in-observatory.iam.gserviceaccount.com, 00m10s elapsed]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0]: Still destroying... [id=projects/prod-fin-observatory/locations...in-observatory.iam.gserviceaccount.com, 00m20s elapsed]
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_invoker[0]: Destruction complete after 18s
module.stack.google_cloud_run_v2_job_iam_member.workflow_pre_developer[0]: Destruction complete after 23s
module.stack.module.ingestion_preprocessing_job[0].google_cloud_run_v2_job.dc_data_job: Destroying... [id=projects/prod-fin-observatory/locations/europe-west1/jobs/dfo-prod-dc-ingestion-preprocessing-job]


Error: cannot destroy job without setting deletion_protection=false and running `terraform apply`

Stack dcp · a19bafe · @jm-rivera · run

@github-actions

Copy link
Copy Markdown

Terraform Apply — telemetry

Apply complete! Resources: 29 added, 0 changed, 0 destroyed.

Init Validate Apply
pass pass pass
Show apply output
google_project_iam_member.searchconsole_export_job_user: Creating...
google_project_service.apis["logging.googleapis.com"]: Creating...
google_service_account.logs_daily: Creating...
google_project_service.apis["bigquery.googleapis.com"]: Creating...
google_project_iam_member.reporting_readers_mcp_tool_user["dashboard-readers"]: Creating...
google_project_iam_member.reporting_readers_job_user["dashboard-readers"]: Creating...
google_project_service.apis["bigquerydatatransfer.googleapis.com"]: Creating...
google_monitoring_notification_channel.alert_email["team"]: Creating...
google_monitoring_notification_channel.alert_email["team"]: Creation complete after 1s [id=projects/prod-fin-observatory/notificationChannels/11474890588894136266]
google_monitoring_alert_policy.export_job_not_succeeding["website_export"]: Creating...
google_monitoring_alert_policy.export_job_not_succeeding["langfuse_export"]: Creating...
google_monitoring_alert_policy.export_job_failed["langfuse_export"]: Creating...
google_monitoring_alert_policy.export_job_not_succeeding["website_export"]: Creation complete after 1s [id=projects/prod-fin-observatory/alertPolicies/537070617641105687]
google_monitoring_alert_policy.export_job_failed["website_export"]: Creating...
google_monitoring_alert_policy.export_job_not_succeeding["langfuse_export"]: Creation complete after 2s [id=projects/prod-fin-observatory/alertPolicies/537070617641103737]
google_project_service.apis["logging.googleapis.com"]: Creation complete after 4s [id=prod-fin-observatory/logging.googleapis.com]
google_project_service.apis["bigquerydatatransfer.googleapis.com"]: Creation complete after 4s [id=prod-fin-observatory/bigquerydatatransfer.googleapis.com]
google_project_service.apis["bigquery.googleapis.com"]: Creation complete after 4s [id=prod-fin-observatory/bigquery.googleapis.com]
google_logging_project_bucket_config.telemetry: Creating...
google_bigquery_dataset.searchconsole: Creating...
google_bigquery_dataset.logs_daily: Creating...
google_bigquery_dataset.reporting: Creating...
google_monitoring_alert_policy.export_job_failed["langfuse_export"]: Creation complete after 4s [id=projects/prod-fin-observatory/alertPolicies/3404035335298455861]
google_bigquery_dataset.logs_daily: Creation complete after 2s [id=projects/prod-fin-observatory/datasets/logs_daily]
google_bigquery_routine.normalise_route: Creating...
google_bigquery_dataset.reporting: Creation complete after 2s [id=projects/prod-fin-observatory/datasets/dfo_reporting]
google_bigquery_dataset_access.reporting_readers["dashboard-readers"]: Creating...
google_bigquery_dataset.searchconsole: Creation complete after 2s [id=projects/prod-fin-observatory/datasets/searchconsole]
google_bigquery_dataset_access.searchconsole_export_writer: Creating...
google_monitoring_alert_policy.export_job_failed["website_export"]: Creation complete after 4s [id=projects/prod-fin-observatory/alertPolicies/11084972590574586978]
google_bigquery_routine.normalise_route: Creation complete after 0s [id=projects/prod-fin-observatory/datasets/logs_daily/routines/normalise_route]
google_project_iam_member.reporting_readers_job_user["dashboard-readers"]: Creation complete after 8s [id=prod-fin-observatory/roles/bigquery.jobUser/***]
google_project_iam_member.searchconsole_export_job_user: Creation complete after 8s [id=prod-fin-observatory/roles/bigquery.jobUser/serviceAccount:search-console-data-export@system.gserviceaccount.com]
google_project_iam_member.reporting_readers_mcp_tool_user["dashboard-readers"]: Creation complete after 8s [id=prod-fin-observatory/roles/mcp.toolUser/***]
google_bigquery_dataset_access.reporting_readers["dashboard-readers"]: Creation complete after 3s [id=projects/prod-fin-observatory/datasets/dfo_reporting]
google_bigquery_dataset_access.searchconsole_export_writer: Creation complete after 3s [id=projects/prod-fin-observatory/datasets/searchconsole]
google_service_account.logs_daily: Still creating... [00m10s elapsed]
google_service_account.logs_daily: Creation complete after 12s [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com]
google_service_account_iam_member.logs_daily_transfer_agent: Creating...
google_project_iam_member.logs_daily_job_user: Creating...
google_bigquery_dataset_access.logs_daily_writer: Creating...
google_logging_project_bucket_config.telemetry: Still creating... [00m10s elapsed]
google_bigquery_dataset_access.logs_daily_writer: Creation complete after 3s [id=projects/prod-fin-observatory/datasets/logs_daily]
google_service_account_iam_member.logs_daily_transfer_agent: Creation complete after 4s [id=projects/prod-fin-observatory/serviceAccounts/dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com/roles/iam.serviceAccountTokenCreator/serviceAccount:service-533754688761@gcp-sa-bigquerydatatransfer.iam.gserviceaccount.com]
google_project_iam_member.logs_daily_job_user: Creation complete after 8s [id=prod-fin-observatory/roles/bigquery.jobUser/serviceAccount:dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com]
google_logging_project_bucket_config.telemetry: Still creating... [00m20s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [00m30s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [00m40s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [00m50s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [01m00s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [01m10s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [01m20s elapsed]
google_logging_project_bucket_config.telemetry: Still creating... [01m30s elapsed]
google_logging_project_bucket_config.telemetry: Creation complete after 1m31s [id=projects/prod-fin-observatory/locations/eu/buckets/dfo-prod-telemetry]
google_logging_linked_dataset.telemetry: Creating...
google_logging_project_sink.telemetry: Creating...
google_logging_project_sink.telemetry: Creation complete after 0s [id=projects/prod-fin-observatory/sinks/dfo-prod-telemetry]
google_logging_linked_dataset.telemetry: Still creating... [00m10s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [00m20s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [00m30s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [00m40s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [00m50s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m00s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m10s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m20s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m30s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m40s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [01m50s elapsed]
google_logging_linked_dataset.telemetry: Still creating... [02m00s elapsed]
google_logging_linked_dataset.telemetry: Creation complete after 2m1s [id=projects/prod-fin-observatory/locations/eu/buckets/dfo-prod-telemetry/links/dfo_logs]
google_bigquery_dataset_access.logs_daily_source_reader: Creating...
google_bigquery_dataset_access.logs_daily_source_reader: Creation complete after 4s [id=projects/prod-fin-observatory/datasets/dfo_logs]
google_bigquery_data_transfer_config.logs_daily: Creating...
google_bigquery_data_transfer_config.logs_daily: Creation complete after 0s [id=projects/533754688761/locations/europe/transferConfigs/6adc862a-0000-2012-b0a5-582429d0fd4c]
google_logging_metric.logs_daily_failed: Creating...
google_logging_metric.logs_daily_failed: Creation complete after 1s [id=dfo-prod-logs-daily-failed]
time_sleep.logs_daily_failed_metric_propagation: Creating...
time_sleep.logs_daily_failed_metric_propagation: Still creating... [00m10s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [00m20s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [00m30s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [00m40s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [00m50s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m00s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m10s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m20s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m30s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m40s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Still creating... [01m50s elapsed]
time_sleep.logs_daily_failed_metric_propagation: Creation complete after 2m0s [id=2026-10-23T18:50:03Z]
google_monitoring_alert_policy.logs_daily_failed: Creating...
google_monitoring_alert_policy.logs_daily_failed: Creation complete after 2s [id=projects/prod-fin-observatory/alertPolicies/14785637027612064735]
Releasing state lock. This may take a few moments...

Apply complete! Resources: 29 added, 0 changed, 0 destroyed.

Outputs:

logs_daily_dataset = "prod-fin-observatory.logs_daily"
logs_daily_service_account = "dfo-prod-logs-daily@prod-fin-observatory.iam.gserviceaccount.com"
logs_linked_dataset = "prod-fin-observatory.dfo_logs"
reporting_dataset = "prod-fin-observatory.dfo_reporting"
searchconsole_dataset = "searchconsole"

Stack telemetry · a19bafe · @jm-rivera · run

This branch was successfully deployed

1 active and 1 inactive deployments
dev — b52ff454 Deployed Oct 23, 2026 by jm-rivera via apply (dcp) / apply #47
plan — b52ff454 Deployed Oct 23, 2026 by jm-rivera via Prod plan (ai) #41
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.

1 participant