agent-starter-pack 0.7.0__py3-none-any.whl → 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/METADATA +5 -5
  2. {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/RECORD +57 -55
  3. agents/README.md +7 -0
  4. agents/adk_base/notebooks/adk_app_testing.ipynb +8 -6
  5. agents/adk_base/template/.templateconfig.yaml +3 -1
  6. agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb +8 -6
  7. agents/adk_gemini_fullstack/template/.templateconfig.yaml +2 -1
  8. agents/agentic_rag/notebooks/adk_app_testing.ipynb +8 -6
  9. agents/agentic_rag/template/.templateconfig.yaml +2 -1
  10. agents/crewai_coding_crew/template/.templateconfig.yaml +1 -1
  11. llm.txt +22 -9
  12. src/base_template/.gitignore +0 -1
  13. src/base_template/README.md +5 -2
  14. src/base_template/deployment/cd/deploy-to-prod.yaml +1 -16
  15. src/base_template/deployment/cd/staging.yaml +4 -19
  16. src/base_template/deployment/terraform/apis.tf +2 -2
  17. src/base_template/deployment/terraform/build_triggers.tf +5 -5
  18. src/base_template/deployment/terraform/dev/apis.tf +8 -1
  19. src/base_template/deployment/terraform/dev/variables.tf +3 -1
  20. src/base_template/deployment/terraform/iam.tf +8 -8
  21. src/base_template/deployment/terraform/locals.tf +9 -2
  22. src/base_template/deployment/terraform/log_sinks.tf +2 -2
  23. src/base_template/deployment/terraform/service_accounts.tf +3 -3
  24. src/base_template/deployment/terraform/storage.tf +7 -7
  25. src/base_template/deployment/terraform/variables.tf +3 -0
  26. src/base_template/pyproject.toml +4 -3
  27. src/cli/commands/create.py +38 -0
  28. src/cli/commands/setup_cicd.py +2 -2
  29. src/cli/utils/cicd.py +6 -3
  30. src/cli/utils/template.py +34 -9
  31. src/deployment_targets/agent_engine/app/agent_engine_app.py +7 -7
  32. src/deployment_targets/agent_engine/tests/load_test/README.md +1 -6
  33. src/deployment_targets/agent_engine/tests/load_test/load_test.py +13 -3
  34. src/deployment_targets/cloud_run/Dockerfile +3 -0
  35. src/deployment_targets/cloud_run/app/server.py +18 -0
  36. src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +231 -0
  37. src/deployment_targets/cloud_run/deployment/terraform/service.tf +360 -0
  38. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +8 -5
  39. src/deployment_targets/cloud_run/tests/load_test/README.md +2 -2
  40. src/deployment_targets/cloud_run/tests/load_test/load_test.py +21 -17
  41. src/frontends/adk_gemini_fullstack/frontend/src/App.tsx +2 -3
  42. src/resources/docs/adk-cheatsheet.md +1 -1
  43. src/resources/locks/uv-adk_base-agent_engine.lock +805 -200
  44. src/resources/locks/uv-adk_base-cloud_run.lock +1085 -234
  45. src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +805 -200
  46. src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +1085 -234
  47. src/resources/locks/uv-agentic_rag-agent_engine.lock +386 -283
  48. src/resources/locks/uv-agentic_rag-cloud_run.lock +513 -349
  49. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +492 -497
  50. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +671 -613
  51. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +500 -391
  52. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +682 -510
  53. src/resources/locks/uv-live_api-cloud_run.lock +686 -486
  54. src/resources/setup_cicd/github.tf +2 -2
  55. src/deployment_targets/cloud_run/uv.lock +0 -6952
  56. {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/WHEEL +0 -0
  57. {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/entry_points.txt +0 -0
  58. {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,231 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Get project information to access the project number
16
+ data "google_project" "project" {
17
+ project_id = var.dev_project_id
18
+ }
19
+
20
+
21
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
22
+
23
+ # VPC Network for AlloyDB
24
+ resource "google_compute_network" "default" {
25
+ name = "${var.project_name}-alloydb-network"
26
+ project = var.dev_project_id
27
+ auto_create_subnetworks = false
28
+ depends_on = [resource.google_project_service.services]
29
+ }
30
+
31
+ # Subnet for AlloyDB
32
+ resource "google_compute_subnetwork" "default" {
33
+ name = "${var.project_name}-alloydb-network"
34
+ ip_cidr_range = "10.0.0.0/24"
35
+ region = var.region
36
+ network = google_compute_network.default.id
37
+ project = var.dev_project_id
38
+
39
+ # This is required for Cloud Run VPC connectors
40
+ purpose = "PRIVATE"
41
+
42
+ private_ip_google_access = true
43
+ }
44
+
45
+ # Private IP allocation for AlloyDB
46
+ resource "google_compute_global_address" "private_ip_alloc" {
47
+ name = "${var.project_name}-private-ip"
48
+ project = var.dev_project_id
49
+ address_type = "INTERNAL"
50
+ purpose = "VPC_PEERING"
51
+ prefix_length = 16
52
+ network = google_compute_network.default.id
53
+
54
+ depends_on = [resource.google_project_service.services]
55
+ }
56
+
57
+ # VPC connection for AlloyDB
58
+ resource "google_service_networking_connection" "vpc_connection" {
59
+ network = google_compute_network.default.id
60
+ service = "servicenetworking.googleapis.com"
61
+ reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
62
+ }
63
+
64
+ # AlloyDB Cluster
65
+ resource "google_alloydb_cluster" "session_db_cluster" {
66
+ project = var.dev_project_id
67
+ cluster_id = "${var.project_name}-alloydb-cluster"
68
+ location = var.region
69
+
70
+ network_config {
71
+ network = google_compute_network.default.id
72
+ }
73
+
74
+ depends_on = [
75
+ google_service_networking_connection.vpc_connection
76
+ ]
77
+ }
78
+
79
+ # AlloyDB Instance
80
+ resource "google_alloydb_instance" "session_db_instance" {
81
+ cluster = google_alloydb_cluster.session_db_cluster.name
82
+ instance_id = "${var.project_name}-alloydb-instance"
83
+ instance_type = "PRIMARY"
84
+
85
+ availability_type = "REGIONAL" # Regional redundancy
86
+
87
+ machine_config {
88
+ cpu_count = 2
89
+ }
90
+ }
91
+
92
+ # Generate a random password for the database user
93
+ resource "random_password" "db_password" {
94
+ length = 16
95
+ special = true
96
+ override_special = "!#$%&*()-_=+[]{}<>:?"
97
+ }
98
+
99
+ # Store the password in Secret Manager
100
+ resource "google_secret_manager_secret" "db_password" {
101
+ project = var.dev_project_id
102
+ secret_id = "${var.project_name}-db-password"
103
+
104
+ replication {
105
+ auto {}
106
+ }
107
+
108
+ depends_on = [resource.google_project_service.services]
109
+ }
110
+
111
+ resource "google_secret_manager_secret_version" "db_password" {
112
+ secret = google_secret_manager_secret.db_password.id
113
+ secret_data = random_password.db_password.result
114
+ }
115
+
116
+ resource "google_alloydb_user" "db_user" {
117
+ cluster = google_alloydb_cluster.session_db_cluster.name
118
+ user_id = "postgres"
119
+ user_type = "ALLOYDB_BUILT_IN"
120
+ password = random_password.db_password.result
121
+ database_roles = ["alloydbsuperuser"]
122
+
123
+ depends_on = [google_alloydb_instance.session_db_instance]
124
+ }
125
+
126
+ {%- endif %}
127
+
128
+
129
+ resource "google_cloud_run_v2_service" "app" {
130
+ name = var.project_name
131
+ location = var.region
132
+ project = var.dev_project_id
133
+ deletion_protection = false
134
+ ingress = "INGRESS_TRAFFIC_ALL"
135
+
136
+ template {
137
+ containers {
138
+ image = "us-docker.pkg.dev/cloudrun/container/hello"
139
+
140
+ resources {
141
+ limits = {
142
+ cpu = "4"
143
+ memory = "8Gi"
144
+ }
145
+ }
146
+ {%- if cookiecutter.data_ingestion %}
147
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
148
+
149
+ env {
150
+ name = "DATA_STORE_ID"
151
+ value = resource.google_discovery_engine_data_store.data_store_dev.data_store_id
152
+ }
153
+
154
+ env {
155
+ name = "DATA_STORE_REGION"
156
+ value = var.data_store_region
157
+ }
158
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
159
+ env {
160
+ name = "VECTOR_SEARCH_INDEX"
161
+ value = resource.google_vertex_ai_index.vector_search_index.id
162
+ }
163
+
164
+ env {
165
+ name = "VECTOR_SEARCH_INDEX_ENDPOINT"
166
+ value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint.id
167
+ }
168
+
169
+ env {
170
+ name = "VECTOR_SEARCH_BUCKET"
171
+ value = "gs://${resource.google_storage_bucket.data_ingestion_PIPELINE_GCS_ROOT.name}"
172
+ }
173
+ {%- endif %}
174
+ {%- endif %}
175
+
176
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
177
+
178
+ env {
179
+ name = "DB_HOST"
180
+ value = google_alloydb_instance.session_db_instance.ip_address
181
+ }
182
+
183
+ env {
184
+ name = "DB_PASS"
185
+ value_source {
186
+ secret_key_ref {
187
+ secret = google_secret_manager_secret.db_password.secret_id
188
+ version = "latest"
189
+ }
190
+ }
191
+ }
192
+ {%- endif %}
193
+ }
194
+
195
+ service_account = google_service_account.cloud_run_app_sa.email
196
+ max_instance_request_concurrency = 40
197
+
198
+ scaling {
199
+ min_instance_count = 1
200
+ max_instance_count = 10
201
+ }
202
+
203
+ session_affinity = true
204
+
205
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
206
+ # VPC access for AlloyDB connectivity
207
+ vpc_access {
208
+ network_interfaces {
209
+ network = google_compute_network.default.id
210
+ subnetwork = google_compute_subnetwork.default.id
211
+ }
212
+ }
213
+ {%- endif %}
214
+ }
215
+
216
+ traffic {
217
+ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
218
+ percent = 100
219
+ }
220
+
221
+ # This lifecycle block prevents Terraform from overwriting the container image when it's
222
+ # updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
223
+ lifecycle {
224
+ ignore_changes = [
225
+ template[0].containers[0].image,
226
+ ]
227
+ }
228
+
229
+ # Make dependencies conditional to avoid errors.
230
+ depends_on = [resource.google_project_service.services]
231
+ }
@@ -0,0 +1,360 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Get project information to access the project number
16
+ data "google_project" "project" {
17
+ for_each = local.deploy_project_ids
18
+
19
+ project_id = local.deploy_project_ids[each.key]
20
+ }
21
+
22
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
23
+
24
+ # VPC Network for AlloyDB
25
+ resource "google_compute_network" "default" {
26
+ for_each = local.deploy_project_ids
27
+
28
+ name = "${var.project_name}-alloydb-network"
29
+ project = local.deploy_project_ids[each.key]
30
+ auto_create_subnetworks = false
31
+
32
+ depends_on = [google_project_service.deploy_project_services]
33
+ }
34
+
35
+ # Subnet for AlloyDB
36
+ resource "google_compute_subnetwork" "default" {
37
+ for_each = local.deploy_project_ids
38
+
39
+ name = "${var.project_name}-alloydb-network"
40
+ ip_cidr_range = "10.0.0.0/24"
41
+ region = var.region
42
+ network = google_compute_network.default[each.key].id
43
+ project = local.deploy_project_ids[each.key]
44
+
45
+ # This is required for Cloud Run VPC connectors
46
+ purpose = "PRIVATE"
47
+
48
+ private_ip_google_access = true
49
+ }
50
+
51
+ # Private IP allocation for AlloyDB
52
+ resource "google_compute_global_address" "private_ip_alloc" {
53
+ for_each = local.deploy_project_ids
54
+
55
+ name = "${var.project_name}-private-ip"
56
+ project = local.deploy_project_ids[each.key]
57
+ address_type = "INTERNAL"
58
+ purpose = "VPC_PEERING"
59
+ prefix_length = 16
60
+ network = google_compute_network.default[each.key].id
61
+
62
+ depends_on = [google_project_service.deploy_project_services]
63
+ }
64
+
65
+ # VPC connection for AlloyDB
66
+ resource "google_service_networking_connection" "vpc_connection" {
67
+ for_each = local.deploy_project_ids
68
+
69
+ network = google_compute_network.default[each.key].id
70
+ service = "servicenetworking.googleapis.com"
71
+ reserved_peering_ranges = [google_compute_global_address.private_ip_alloc[each.key].name]
72
+ }
73
+
74
+ # AlloyDB Cluster
75
+ resource "google_alloydb_cluster" "session_db_cluster" {
76
+ for_each = local.deploy_project_ids
77
+
78
+ project = local.deploy_project_ids[each.key]
79
+ cluster_id = "${var.project_name}-alloydb-cluster"
80
+ location = var.region
81
+
82
+ network_config {
83
+ network = google_compute_network.default[each.key].id
84
+ }
85
+
86
+ depends_on = [
87
+ google_service_networking_connection.vpc_connection
88
+ ]
89
+ }
90
+
91
+ # AlloyDB Instance
92
+ resource "google_alloydb_instance" "session_db_instance" {
93
+ for_each = local.deploy_project_ids
94
+
95
+ cluster = google_alloydb_cluster.session_db_cluster[each.key].name
96
+ instance_id = "${var.project_name}-alloydb-instance"
97
+ instance_type = "PRIMARY"
98
+
99
+ availability_type = "REGIONAL" # Regional redundancy
100
+
101
+ machine_config {
102
+ cpu_count = 2
103
+ }
104
+ }
105
+
106
+ # Generate a random password for the database user
107
+ resource "random_password" "db_password" {
108
+ for_each = local.deploy_project_ids
109
+
110
+ length = 16
111
+ special = true
112
+ override_special = "!#$%&*()-_=+[]{}<>:?"
113
+ }
114
+
115
+ # Store the password in Secret Manager
116
+ resource "google_secret_manager_secret" "db_password" {
117
+ for_each = local.deploy_project_ids
118
+
119
+ project = local.deploy_project_ids[each.key]
120
+ secret_id = "${var.project_name}-db-password"
121
+
122
+ replication {
123
+ auto {}
124
+ }
125
+
126
+ depends_on = [google_project_service.deploy_project_services]
127
+ }
128
+
129
+ resource "google_secret_manager_secret_version" "db_password" {
130
+ for_each = local.deploy_project_ids
131
+
132
+ secret = google_secret_manager_secret.db_password[each.key].id
133
+ secret_data = random_password.db_password[each.key].result
134
+ }
135
+
136
+ resource "google_alloydb_user" "db_user" {
137
+ for_each = local.deploy_project_ids
138
+
139
+ cluster = google_alloydb_cluster.session_db_cluster[each.key].name
140
+ user_id = "postgres"
141
+ user_type = "ALLOYDB_BUILT_IN"
142
+ password = random_password.db_password[each.key].result
143
+ database_roles = ["alloydbsuperuser"]
144
+
145
+ depends_on = [google_alloydb_instance.session_db_instance]
146
+ }
147
+
148
+ {%- endif %}
149
+
150
+ resource "google_cloud_run_v2_service" "app_staging" {
151
+ name = var.project_name
152
+ location = var.region
153
+ project = var.staging_project_id
154
+ deletion_protection = false
155
+ ingress = "INGRESS_TRAFFIC_ALL"
156
+
157
+ template {
158
+ containers {
159
+ # Placeholder, will be replaced by the CI/CD pipeline
160
+ image = "us-docker.pkg.dev/cloudrun/container/hello"
161
+
162
+ resources {
163
+ limits = {
164
+ cpu = "4"
165
+ memory = "8Gi"
166
+ }
167
+ cpu_idle = false
168
+ }
169
+ {%- if cookiecutter.data_ingestion %}
170
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
171
+
172
+ env {
173
+ name = "DATA_STORE_ID"
174
+ value = resource.google_discovery_engine_data_store.data_store_staging.data_store_id
175
+ }
176
+
177
+ env {
178
+ name = "DATA_STORE_REGION"
179
+ value = var.data_store_region
180
+ }
181
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
182
+ env {
183
+ name = "VECTOR_SEARCH_INDEX"
184
+ value = resource.google_vertex_ai_index.vector_search_index_staging.id
185
+ }
186
+
187
+ env {
188
+ name = "VECTOR_SEARCH_INDEX_ENDPOINT"
189
+ value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_staging.id
190
+ }
191
+
192
+ env {
193
+ name = "VECTOR_SEARCH_BUCKET"
194
+ value = resource.google_storage_bucket.vector_search_data_bucket["staging"].url
195
+ }
196
+ {%- endif %}
197
+ {%- endif %}
198
+
199
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
200
+
201
+ env {
202
+ name = "DB_HOST"
203
+ value = google_alloydb_instance.session_db_instance["staging"].ip_address
204
+ }
205
+
206
+ env {
207
+ name = "DB_PASS"
208
+ value_source {
209
+ secret_key_ref {
210
+ secret = google_secret_manager_secret.db_password["staging"].secret_id
211
+ version = "latest"
212
+ }
213
+ }
214
+ }
215
+ {%- endif %}
216
+ }
217
+
218
+ service_account = google_service_account.cloud_run_app_sa["staging"].email
219
+ max_instance_request_concurrency = 40
220
+
221
+ scaling {
222
+ min_instance_count = 1
223
+ max_instance_count = 10
224
+ }
225
+
226
+ session_affinity = true
227
+
228
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
229
+ # VPC access for AlloyDB connectivity
230
+ vpc_access {
231
+ network_interfaces {
232
+ network = google_compute_network.default["staging"].id
233
+ subnetwork = google_compute_subnetwork.default["staging"].id
234
+ }
235
+ }
236
+ {%- endif %}
237
+ }
238
+
239
+ traffic {
240
+ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
241
+ percent = 100
242
+ }
243
+
244
+ # This lifecycle block prevents Terraform from overwriting the container image when it's
245
+ # updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
246
+ lifecycle {
247
+ ignore_changes = [
248
+ template[0].containers[0].image,
249
+ ]
250
+ }
251
+
252
+ # Make dependencies conditional to avoid errors.
253
+ depends_on = [google_project_service.deploy_project_services]
254
+ }
255
+
256
+ resource "google_cloud_run_v2_service" "app_prod" {
257
+ name = var.project_name
258
+ location = var.region
259
+ project = var.prod_project_id
260
+ deletion_protection = false
261
+ ingress = "INGRESS_TRAFFIC_ALL"
262
+
263
+ template {
264
+ containers {
265
+ # Placeholder, will be replaced by the CI/CD pipeline
266
+ image = "us-docker.pkg.dev/cloudrun/container/hello"
267
+
268
+ resources {
269
+ limits = {
270
+ cpu = "4"
271
+ memory = "8Gi"
272
+ }
273
+ cpu_idle = false
274
+ }
275
+ {%- if cookiecutter.data_ingestion %}
276
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
277
+
278
+ env {
279
+ name = "DATA_STORE_ID"
280
+ value = resource.google_discovery_engine_data_store.data_store_prod.data_store_id
281
+ }
282
+
283
+ env {
284
+ name = "DATA_STORE_REGION"
285
+ value = var.data_store_region
286
+ }
287
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
288
+ env {
289
+ name = "VECTOR_SEARCH_INDEX"
290
+ value = resource.google_vertex_ai_index.vector_search_index_prod.id
291
+ }
292
+
293
+ env {
294
+ name = "VECTOR_SEARCH_INDEX_ENDPOINT"
295
+ value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_prod.id
296
+ }
297
+
298
+ env {
299
+ name = "VECTOR_SEARCH_BUCKET"
300
+ value = resource.google_storage_bucket.vector_search_data_bucket["prod"].url
301
+ }
302
+ {%- endif %}
303
+ {%- endif %}
304
+
305
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
306
+
307
+ env {
308
+ name = "DB_HOST"
309
+ value = google_alloydb_instance.session_db_instance["prod"].ip_address
310
+ }
311
+
312
+ env {
313
+ name = "DB_PASS"
314
+ value_source {
315
+ secret_key_ref {
316
+ secret = google_secret_manager_secret.db_password["prod"].secret_id
317
+ version = "latest"
318
+ }
319
+ }
320
+ }
321
+ {%- endif %}
322
+ }
323
+
324
+ service_account = google_service_account.cloud_run_app_sa["prod"].email
325
+ max_instance_request_concurrency = 40
326
+
327
+ scaling {
328
+ min_instance_count = 1
329
+ max_instance_count = 10
330
+ }
331
+
332
+ session_affinity = true
333
+
334
+ {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
335
+ # VPC access for AlloyDB connectivity
336
+ vpc_access {
337
+ network_interfaces {
338
+ network = google_compute_network.default["prod"].id
339
+ subnetwork = google_compute_subnetwork.default["prod"].id
340
+ }
341
+ }
342
+ {%- endif %}
343
+ }
344
+
345
+ traffic {
346
+ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
347
+ percent = 100
348
+ }
349
+
350
+ # This lifecycle block prevents Terraform from overwriting the container image when it's
351
+ # updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
352
+ lifecycle {
353
+ ignore_changes = [
354
+ template[0].containers[0].image,
355
+ ]
356
+ }
357
+
358
+ # Make dependencies conditional to avoid errors.
359
+ depends_on = [google_project_service.deploy_project_services]
360
+ }
@@ -122,16 +122,19 @@ def test_chat_stream(server_fixture: subprocess.Popen[str]) -> None:
122
122
  logger.info("Starting chat stream test")
123
123
  {% if "adk" in cookiecutter.tags %}
124
124
  # Create session first
125
- user_id = "user_123"
126
- session_id = "session_abc"
127
- session_data = {"state": {"preferred_language": "English", "visit_count": 5}}
125
+ user_id = "test_user_123"
126
+ session_data = {"state": {"preferred_language": "English", "visit_count": 1}}
127
+
128
+ session_url = f"{BASE_URL}/apps/app/users/{user_id}/sessions"
128
129
  session_response = requests.post(
129
- f"{BASE_URL}/apps/app/users/{user_id}/sessions/{session_id}",
130
+ session_url,
130
131
  headers=HEADERS,
131
132
  json=session_data,
132
- timeout=10,
133
+ timeout=60,
133
134
  )
134
135
  assert session_response.status_code == 200
136
+ logger.info(f"Session creation response: {session_response.json()}")
137
+ session_id = session_response.json()["id"]
135
138
 
136
139
  # Then send chat message
137
140
  data = {
@@ -18,7 +18,7 @@ uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload
18
18
  Using another terminal tab, This is suggested to avoid conflicts with the existing application python environment.
19
19
 
20
20
  ```bash
21
- python3 -m venv .locust_env && source locust_env/bin/activate && pip install locust==2.31.1
21
+ python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1
22
22
  ```
23
23
 
24
24
  **3. Execute the Load Test:**
@@ -69,7 +69,7 @@ export _ID_TOKEN=$(gcloud auth print-identity-token -q)
69
69
  **3. Execute the Load Test:**
70
70
  Create virtual environment with Locust:
71
71
  ```bash
72
- python3 -m venv .locust_env && source locust_env/bin/activate && pip install locust==2.31.1
72
+ python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1
73
73
  ```
74
74
 
75
75
  Execute load tests. The following command executes the same load test parameters as the local test but targets your remote Cloud Run instance.