From a81adf2cc81fc6f2ff8e8514f8a8c14a15fd1603 Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:38:00 +0000 Subject: [PATCH 1/6] feat(azure): add optional timer schedule for container build --- modules/azure/container_registry.tf | 5 +++++ modules/azure/variables.tf | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/azure/container_registry.tf b/modules/azure/container_registry.tf index 5b1c40c..c10fc15 100644 --- a/modules/azure/container_registry.tf +++ b/modules/azure/container_registry.tf @@ -36,6 +36,11 @@ resource "azurerm_container_registry_task" "alz" { identity { type = "SystemAssigned" # Note this has to be a System Assigned Identity to work with private networking and `network_rule_bypass_option` set to `AzureServices` } + timer_trigger { + name = "scheduled-build" + schedule = var.container_registry_task_timer_trigger_schedule + enabled = var.container_registry_task_timer_trigger_enabled + } registry_credential { custom { login_server = azurerm_container_registry.alz[0].login_server diff --git a/modules/azure/variables.tf b/modules/azure/variables.tf index 80d7087..c93eae7 100644 --- a/modules/azure/variables.tf +++ b/modules/azure/variables.tf @@ -498,6 +498,30 @@ variable "container_registry_image_tag" { default = "{{.Run.ID}}" } +variable "container_registry_task_timer_trigger_enabled" { + description = <<-EOT + **(Optional, default: `true`)** Enable daily timer trigger for container registry image builds. + + When enabled, the ACR task runs daily to rebuild the agent image, + ensuring it stays up-to-date with latest patches and dependencies. + + See container_registry_task_timer_trigger_schedule for customizing the schedule. + EOT + type = bool + default = true +} + +variable "container_registry_task_timer_trigger_schedule" { + description = <<-EOT + **(Optional, default: `"0 0 * * 0"`)** CRON schedule for the container registry task timer trigger. + + Default schedule runs at midnight on Sundays. + Modify as needed to fit maintenance windows or update frequency. + EOT + type = string + default = "0 0 * * 0" +} + variable "use_self_hosted_agents" { description = <<-EOT **(Optional, default: `true`)** Controls whether to deploy self-hosted CI/CD agents in Azure Container Instances. From 25c8de8aad725fbaff6ccd8db13d0a4869675c2f Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:39:53 +0000 Subject: [PATCH 2/6] feat: ensure variables are not nullable --- modules/azure/variables.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/azure/variables.tf b/modules/azure/variables.tf index c93eae7..fc03898 100644 --- a/modules/azure/variables.tf +++ b/modules/azure/variables.tf @@ -507,6 +507,7 @@ variable "container_registry_task_timer_trigger_enabled" { See container_registry_task_timer_trigger_schedule for customizing the schedule. EOT + nullable = false type = bool default = true } @@ -519,6 +520,7 @@ variable "container_registry_task_timer_trigger_schedule" { Modify as needed to fit maintenance windows or update frequency. EOT type = string + nullable = false default = "0 0 * * 0" } From 59902c44a249b48de1d2145ed91cd48f3c43f02e Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:41:31 +0000 Subject: [PATCH 3/6] fix: variable wording --- modules/azure/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure/variables.tf b/modules/azure/variables.tf index fc03898..a7c954f 100644 --- a/modules/azure/variables.tf +++ b/modules/azure/variables.tf @@ -500,7 +500,7 @@ variable "container_registry_image_tag" { variable "container_registry_task_timer_trigger_enabled" { description = <<-EOT - **(Optional, default: `true`)** Enable daily timer trigger for container registry image builds. + **(Optional, default: `true`)** Enable timer trigger for container registry image builds When enabled, the ACR task runs daily to rebuild the agent image, ensuring it stays up-to-date with latest patches and dependencies. From fe739d51c96ef38aedd9800b965e91df36f4e8b8 Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:42:21 +0000 Subject: [PATCH 4/6] fix: var desc --- modules/azure/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure/variables.tf b/modules/azure/variables.tf index a7c954f..5d2de28 100644 --- a/modules/azure/variables.tf +++ b/modules/azure/variables.tf @@ -502,7 +502,7 @@ variable "container_registry_task_timer_trigger_enabled" { description = <<-EOT **(Optional, default: `true`)** Enable timer trigger for container registry image builds - When enabled, the ACR task runs daily to rebuild the agent image, + When enabled, the ACR task runs to rebuild the agent image, ensuring it stays up-to-date with latest patches and dependencies. See container_registry_task_timer_trigger_schedule for customizing the schedule. From 219d6eca4422939cb507bac86a0c38673dc99645 Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:13:30 +0000 Subject: [PATCH 5/6] feat(azuredevops): add container task trigger vars --- alz/azuredevops/main.tf | 71 +++++++++++++++++++----------------- alz/azuredevops/variables.tf | 26 +++++++++++++ 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/alz/azuredevops/main.tf b/alz/azuredevops/main.tf index a7b9ab5..31709cf 100644 --- a/alz/azuredevops/main.tf +++ b/alz/azuredevops/main.tf @@ -18,55 +18,57 @@ module "files" { module "azure" { source = "../../modules/azure" - resource_group_identity_name = local.resource_names.resource_group_identity - resource_group_agents_name = local.resource_names.resource_group_agents - resource_group_network_name = local.resource_names.resource_group_network - resource_group_state_name = local.resource_names.resource_group_state - create_storage_account = var.iac_type == local.iac_terraform - storage_account_name = local.resource_names.storage_account - storage_container_name = local.resource_names.storage_container - azure_location = var.bootstrap_location - user_assigned_managed_identities = local.managed_identities - federated_credentials = local.federated_credentials - agent_container_instances = local.agent_container_instances agent_container_instance_managed_identity_name = local.resource_names.container_instance_managed_identity - agent_organization_url = module.azure_devops.organization_url - agent_token = var.azure_devops_agents_personal_access_token + agent_container_instances = local.agent_container_instances + agent_name_environment_variable = var.agent_name_environment_variable agent_organization_environment_variable = var.agent_organization_environment_variable - agent_pool_name = module.azure_devops.agent_pool_name + agent_organization_url = module.azure_devops.organization_url agent_pool_environment_variable = var.agent_pool_environment_variable - agent_name_environment_variable = var.agent_name_environment_variable + agent_pool_name = module.azure_devops.agent_pool_name + agent_token = var.azure_devops_agents_personal_access_token agent_token_environment_variable = var.agent_token_environment_variable - target_subscriptions = local.target_subscriptions - root_parent_management_group_id = local.root_parent_management_group_id - virtual_network_name = local.resource_names.virtual_network - virtual_network_subnet_name_container_instances = local.resource_names.subnet_container_instances - virtual_network_subnet_name_private_endpoints = local.resource_names.subnet_private_endpoints - storage_account_private_endpoint_name = local.resource_names.storage_account_private_endpoint - use_private_networking = local.use_private_networking allow_storage_access_from_my_ip = local.allow_storage_access_from_my_ip - virtual_network_address_space = var.virtual_network_address_space - virtual_network_subnet_address_prefix_container_instances = var.virtual_network_subnet_address_prefix_container_instances - virtual_network_subnet_address_prefix_private_endpoints = var.virtual_network_subnet_address_prefix_private_endpoints - storage_account_replication_type = var.storage_account_replication_type - public_ip_name = local.resource_names.public_ip - nat_gateway_name = local.resource_names.nat_gateway - use_self_hosted_agents = var.use_self_hosted_agents - container_registry_name = local.resource_names.container_registry - container_registry_private_endpoint_name = local.resource_names.container_registry_private_endpoint - container_registry_image_name = local.resource_names.container_image_name - container_registry_image_tag = var.agent_container_image_tag + azure_location = var.bootstrap_location container_registry_dockerfile_name = var.agent_container_image_dockerfile container_registry_dockerfile_repository_folder_url = local.agent_container_instance_dockerfile_url + container_registry_image_name = local.resource_names.container_image_name + container_registry_image_tag = var.agent_container_image_tag + container_registry_name = local.resource_names.container_registry + container_registry_private_endpoint_name = local.resource_names.container_registry_private_endpoint + container_registry_task_timer_trigger_enabled = var.container_registry_task_timer_trigger_enabled + container_registry_task_timer_trigger_schedule = var.container_registry_task_timer_trigger_schedule + create_storage_account = var.iac_type == local.iac_terraform custom_role_definitions = var.iac_type == "terraform" ? local.custom_role_definitions_terraform : (var.iac_type == "bicep" ? local.custom_role_definitions_bicep : local.custom_role_definitions_bicep_classic) + federated_credentials = local.federated_credentials + nat_gateway_name = local.resource_names.nat_gateway + public_ip_name = local.resource_names.public_ip + resource_group_agents_name = local.resource_names.resource_group_agents + resource_group_identity_name = local.resource_names.resource_group_identity + resource_group_network_name = local.resource_names.resource_group_network + resource_group_state_name = local.resource_names.resource_group_state role_assignments = var.iac_type == "terraform" ? var.role_assignments_terraform : var.role_assignments_bicep + root_parent_management_group_id = local.root_parent_management_group_id storage_account_blob_soft_delete_enabled = var.storage_account_blob_soft_delete_enabled storage_account_blob_soft_delete_retention_days = var.storage_account_blob_soft_delete_retention_days storage_account_blob_versioning_enabled = var.storage_account_blob_versioning_enabled storage_account_container_soft_delete_enabled = var.storage_account_container_soft_delete_enabled storage_account_container_soft_delete_retention_days = var.storage_account_container_soft_delete_retention_days + storage_account_name = local.resource_names.storage_account + storage_account_private_endpoint_name = local.resource_names.storage_account_private_endpoint + storage_account_replication_type = var.storage_account_replication_type + storage_container_name = local.resource_names.storage_container + target_subscriptions = local.target_subscriptions tenant_role_assignment_enabled = var.iac_type == "bicep" && var.bicep_tenant_role_assignment_enabled tenant_role_assignment_role_definition_name = var.bicep_tenant_role_assignment_role_definition_name + use_private_networking = local.use_private_networking + use_self_hosted_agents = var.use_self_hosted_agents + user_assigned_managed_identities = local.managed_identities + virtual_network_address_space = var.virtual_network_address_space + virtual_network_name = local.resource_names.virtual_network + virtual_network_subnet_address_prefix_container_instances = var.virtual_network_subnet_address_prefix_container_instances + virtual_network_subnet_address_prefix_private_endpoints = var.virtual_network_subnet_address_prefix_private_endpoints + virtual_network_subnet_name_container_instances = local.resource_names.subnet_container_instances + virtual_network_subnet_name_private_endpoints = local.resource_names.subnet_private_endpoints } module "azure_devops" { @@ -121,4 +123,5 @@ module "file_manipulation" { agent_pool_or_runner_configuration = local.agent_pool_or_runner_configuration pipeline_files_directory_path = local.pipeline_files_directory_path pipeline_template_files_directory_path = local.pipeline_template_files_directory_path -} \ No newline at end of file +} + diff --git a/alz/azuredevops/variables.tf b/alz/azuredevops/variables.tf index f678c00..554d4c4 100644 --- a/alz/azuredevops/variables.tf +++ b/alz/azuredevops/variables.tf @@ -1116,3 +1116,29 @@ variable "bicep_tenant_role_assignment_role_definition_name" { type = string default = "Landing Zone Management Owner" } + +variable "container_registry_task_timer_trigger_enabled" { + description = <<-EOT + **(Optional, default: `true`)** Enable timer trigger for container registry image builds + + When enabled, the ACR task runs to rebuild the agent image, + ensuring it stays up-to-date with latest patches and dependencies. + + See container_registry_task_timer_trigger_schedule for customizing the schedule. + EOT + nullable = false + type = bool + default = true +} + +variable "container_registry_task_timer_trigger_schedule" { + description = <<-EOT + **(Optional, default: `"0 0 * * 0"`)** CRON schedule for the container registry task timer trigger. + + Default schedule runs at midnight on Sundays. + Modify as needed to fit maintenance windows or update frequency. + EOT + type = string + nullable = false + default = "0 0 * * 0" +} From d57cc0465e6e1e8530eecec4c56af96b9b75df6d Mon Sep 17 00:00:00 2001 From: Matt White <16320656+matt-FFFFFF@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:16:14 +0000 Subject: [PATCH 6/6] feat(github): add container cron task vars --- alz/github/main.tf | 70 +++++++++++++++++++++-------------------- alz/github/variables.tf | 26 +++++++++++++++ 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/alz/github/main.tf b/alz/github/main.tf index 4797274..3b1969b 100644 --- a/alz/github/main.tf +++ b/alz/github/main.tf @@ -18,56 +18,58 @@ module "files" { module "azure" { source = "../../modules/azure" - user_assigned_managed_identities = local.managed_identities - federated_credentials = local.federated_credentials - resource_group_identity_name = local.resource_names.resource_group_identity - resource_group_state_name = local.resource_names.resource_group_state - resource_group_agents_name = local.resource_names.resource_group_agents - resource_group_network_name = local.resource_names.resource_group_network - create_storage_account = var.iac_type == local.iac_terraform - storage_account_name = local.resource_names.storage_account - storage_container_name = local.resource_names.storage_container - azure_location = var.bootstrap_location - target_subscriptions = local.target_subscriptions - root_parent_management_group_id = local.root_parent_management_group_id - agent_container_instances = local.runner_container_instances agent_container_instance_managed_identity_name = local.resource_names.container_instance_managed_identity - agent_organization_url = local.runner_organization_repository_url - agent_token = var.github_runners_personal_access_token + agent_container_instances = local.runner_container_instances + agent_name_environment_variable = var.runner_name_environment_variable agent_organization_environment_variable = var.runner_organization_environment_variable - agent_pool_name = local.resource_names.version_control_system_runner_group + agent_organization_url = local.runner_organization_repository_url agent_pool_environment_variable = var.runner_group_environment_variable - agent_name_environment_variable = var.runner_name_environment_variable - use_agent_pool_environment_variable = local.use_runner_group + agent_pool_name = local.resource_names.version_control_system_runner_group + agent_token = var.github_runners_personal_access_token agent_token_environment_variable = var.runner_token_environment_variable - virtual_network_name = local.resource_names.virtual_network - virtual_network_subnet_name_container_instances = local.resource_names.subnet_container_instances - virtual_network_subnet_name_private_endpoints = local.resource_names.subnet_private_endpoints - storage_account_private_endpoint_name = local.resource_names.storage_account_private_endpoint - use_private_networking = local.use_private_networking allow_storage_access_from_my_ip = local.allow_storage_access_from_my_ip - virtual_network_address_space = var.virtual_network_address_space - virtual_network_subnet_address_prefix_container_instances = var.virtual_network_subnet_address_prefix_container_instances - virtual_network_subnet_address_prefix_private_endpoints = var.virtual_network_subnet_address_prefix_private_endpoints - storage_account_replication_type = var.storage_account_replication_type - public_ip_name = local.resource_names.public_ip - nat_gateway_name = local.resource_names.nat_gateway - use_self_hosted_agents = var.use_self_hosted_runners - container_registry_name = local.resource_names.container_registry - container_registry_private_endpoint_name = local.resource_names.container_registry_private_endpoint - container_registry_image_name = local.resource_names.container_image_name - container_registry_image_tag = var.runner_container_image_tag + azure_location = var.bootstrap_location container_registry_dockerfile_name = var.runner_container_image_dockerfile container_registry_dockerfile_repository_folder_url = local.runner_container_instance_dockerfile_url + container_registry_image_name = local.resource_names.container_image_name + container_registry_image_tag = var.runner_container_image_tag + container_registry_name = local.resource_names.container_registry + container_registry_private_endpoint_name = local.resource_names.container_registry_private_endpoint + container_registry_task_timer_trigger_enabled = var.container_registry_task_timer_trigger_enabled + container_registry_task_timer_trigger_schedule = var.container_registry_task_timer_trigger_schedule + create_storage_account = var.iac_type == local.iac_terraform custom_role_definitions = var.iac_type == "terraform" ? local.custom_role_definitions_terraform : (var.iac_type == "bicep" ? local.custom_role_definitions_bicep : local.custom_role_definitions_bicep_classic) + federated_credentials = local.federated_credentials + nat_gateway_name = local.resource_names.nat_gateway + public_ip_name = local.resource_names.public_ip + resource_group_agents_name = local.resource_names.resource_group_agents + resource_group_identity_name = local.resource_names.resource_group_identity + resource_group_network_name = local.resource_names.resource_group_network + resource_group_state_name = local.resource_names.resource_group_state role_assignments = var.iac_type == "terraform" ? var.role_assignments_terraform : var.role_assignments_bicep + root_parent_management_group_id = local.root_parent_management_group_id storage_account_blob_soft_delete_enabled = var.storage_account_blob_soft_delete_enabled storage_account_blob_soft_delete_retention_days = var.storage_account_blob_soft_delete_retention_days storage_account_blob_versioning_enabled = var.storage_account_blob_versioning_enabled storage_account_container_soft_delete_enabled = var.storage_account_container_soft_delete_enabled storage_account_container_soft_delete_retention_days = var.storage_account_container_soft_delete_retention_days + storage_account_name = local.resource_names.storage_account + storage_account_private_endpoint_name = local.resource_names.storage_account_private_endpoint + storage_account_replication_type = var.storage_account_replication_type + storage_container_name = local.resource_names.storage_container + target_subscriptions = local.target_subscriptions tenant_role_assignment_enabled = var.iac_type == "bicep" && var.bicep_tenant_role_assignment_enabled tenant_role_assignment_role_definition_name = var.bicep_tenant_role_assignment_role_definition_name + use_agent_pool_environment_variable = local.use_runner_group + use_private_networking = local.use_private_networking + use_self_hosted_agents = var.use_self_hosted_runners + user_assigned_managed_identities = local.managed_identities + virtual_network_address_space = var.virtual_network_address_space + virtual_network_name = local.resource_names.virtual_network + virtual_network_subnet_address_prefix_container_instances = var.virtual_network_subnet_address_prefix_container_instances + virtual_network_subnet_address_prefix_private_endpoints = var.virtual_network_subnet_address_prefix_private_endpoints + virtual_network_subnet_name_container_instances = local.resource_names.subnet_container_instances + virtual_network_subnet_name_private_endpoints = local.resource_names.subnet_private_endpoints } module "github" { diff --git a/alz/github/variables.tf b/alz/github/variables.tf index bf6bfa3..1ff8cbf 100644 --- a/alz/github/variables.tf +++ b/alz/github/variables.tf @@ -1168,3 +1168,29 @@ variable "bicep_tenant_role_assignment_role_definition_name" { type = string default = "Landing Zone Management Owner" } + +variable "container_registry_task_timer_trigger_enabled" { + description = <<-EOT + **(Optional, default: `true`)** Enable timer trigger for container registry image builds + + When enabled, the ACR task runs to rebuild the agent image, + ensuring it stays up-to-date with latest patches and dependencies. + + See container_registry_task_timer_trigger_schedule for customizing the schedule. + EOT + nullable = false + type = bool + default = true +} + +variable "container_registry_task_timer_trigger_schedule" { + description = <<-EOT + **(Optional, default: `"0 0 * * 0"`)** CRON schedule for the container registry task timer trigger. + + Default schedule runs at midnight on Sundays. + Modify as needed to fit maintenance windows or update frequency. + EOT + type = string + nullable = false + default = "0 0 * * 0" +}