Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Join our discord community via [this invite link](https://discord.gg/bxgXW8jJGh)
| <a name="input_matcher_config_parameter_store_tier"></a> [matcher\_config\_parameter\_store\_tier](#input\_matcher\_config\_parameter\_store\_tier) | The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`. | `string` | `"Standard"` | no |
| <a name="input_metrics"></a> [metrics](#input\_metrics) | Configuration for metrics created by the module, by default disabled to avoid additional costs. When metrics are enable all metrics are created unless explicit configured otherwise. | <pre>object({<br/> enable = optional(bool, false)<br/> namespace = optional(string, "GitHub Runners")<br/> metric = optional(object({<br/> enable_github_app_rate_limit = optional(bool, true)<br/> enable_job_retry = optional(bool, true)<br/> enable_spot_termination_warning = optional(bool, true)<br/> }), {})<br/> })</pre> | `{}` | no |
| <a name="input_minimum_running_time_in_minutes"></a> [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated, if not busy. | `number` | `null` | no |
| <a name="input_parameter_store_tags"></a> [parameter\_store\_tags](#input\_parameter\_store\_tags) | Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function. | `map(string)` | `{}` | no |
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for weekdays to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. Use `schedule_expression_timezone` to override the schedule time zone (defaults to UTC). | <pre>list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = optional(string)<br/> size = number<br/> }))</pre> | `[]` | no |
| <a name="input_pool_lambda_memory_size"></a> [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Memory size limit for scale-up lambda. | `number` | `512` | no |
| <a name="input_pool_lambda_reserved_concurrent_executions"></a> [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no |
Expand Down
4 changes: 4 additions & 0 deletions lambdas/functions/control-plane/src/pool/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export async function adjust(event: PoolEvent): Promise<void> {
const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS
? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string])
: [];
const ssmParameterStoreTags = process.env.SSM_PARAMETER_STORE_TAGS
? JSON.parse(process.env.SSM_PARAMETER_STORE_TAGS)
: {};
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

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

The default value should be an empty array [] instead of an empty object {} to match the expected type structure used in the scale-up function and maintain consistency.

Suggested change
: {};
: [];

Copilot uses AI. Check for mistakes.

const { ghesApiUrl, ghesBaseUrl } = getGitHubEnterpriseApiUrl();

Expand Down Expand Up @@ -81,6 +84,7 @@ export async function adjust(event: PoolEvent): Promise<void> {
disableAutoUpdate: disableAutoUpdate,
ssmTokenPath,
ssmConfigPath,
ssmParameterStoreTags,
},
{
ec2instanceCriteria: {
Expand Down
13 changes: 11 additions & 2 deletions lambdas/functions/control-plane/src/scale-runners/scale-up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ interface CreateGitHubRunnerConfig {
disableAutoUpdate: boolean;
ssmTokenPath: string;
ssmConfigPath: string;
ssmParameterStoreTags: { Key: string; Value: string }[];
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

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

[nitpick] The interface property should use consistent naming. Consider renaming to ssmParameterStoreTags to match the environment variable name pattern or use a more descriptive name like parameterStoreTags.

Suggested change
ssmParameterStoreTags: { Key: string; Value: string }[];
parameterStoreTags: { Key: string; Value: string }[];

Copilot uses AI. Check for mistakes.
}

interface CreateEC2RunnerConfig {
Expand Down Expand Up @@ -182,6 +183,9 @@ async function getRunnerGroupId(githubRunnerConfig: CreateGitHubRunnerConfig, gh
`${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`,
runnerGroupId.toString(),
false,
{
tags: githubRunnerConfig.ssmParameterStoreTags,
},
);
} catch (err) {
logger.debug('Error storing runner group id in SSM Parameter Store', err as Error);
Expand Down Expand Up @@ -251,6 +255,10 @@ export async function scaleUp(eventSource: string, payload: ActionRequestMessage
const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS
? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string])
: [];
const ssmParameterStoreTags: { Key: string; Value: string }[] =
process.env.SSM_PARAMETER_STORE_TAGS && process.env.SSM_PARAMETER_STORE_TAGS.trim() !== ''
? JSON.parse(process.env.SSM_PARAMETER_STORE_TAGS)
: [];

if (ephemeralEnabled && payload.eventType !== 'workflow_job') {
logger.warn(`${payload.eventType} event is not supported in combination with ephemeral runners.`);
Expand Down Expand Up @@ -321,6 +329,7 @@ export async function scaleUp(eventSource: string, payload: ActionRequestMessage
disableAutoUpdate,
ssmTokenPath,
ssmConfigPath,
ssmParameterStoreTags,
},
{
ec2instanceCriteria: {
Expand Down Expand Up @@ -407,7 +416,7 @@ async function createRegistrationTokenConfig(

for (const instance of instances) {
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerServiceConfig.join(' '), true, {
tags: [{ Key: 'InstanceId', Value: instance }],
tags: [{ Key: 'InstanceId', Value: instance }, ...githubRunnerConfig.ssmParameterStoreTags],
});
if (isDelay) {
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
Expand Down Expand Up @@ -465,7 +474,7 @@ async function createJitConfig(githubRunnerConfig: CreateGitHubRunnerConfig, ins
instance: instance,
});
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerConfig.data.encoded_jit_config, true, {
tags: [{ Key: 'InstanceId', Value: instance }],
tags: [{ Key: 'InstanceId', Value: instance }, ...githubRunnerConfig.ssmParameterStoreTags],
});
if (isDelay) {
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
Expand Down
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ module "runners" {
runner_log_files = var.runner_log_files
runner_group_name = var.runner_group_name
runner_name_prefix = var.runner_name_prefix
parameter_store_tags = var.parameter_store_tags

scale_up_reserved_concurrent_executions = var.scale_up_reserved_concurrent_executions

Expand Down
1 change: 1 addition & 0 deletions modules/multi-runner/README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions modules/multi-runner/runners.tf
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ module "runners" {
runner_log_files = each.value.runner_config.runner_log_files
runner_group_name = each.value.runner_config.runner_group_name
runner_name_prefix = each.value.runner_config.runner_name_prefix
parameter_store_tags = var.parameter_store_tags

scale_up_reserved_concurrent_executions = each.value.runner_config.scale_up_reserved_concurrent_executions

Expand Down
6 changes: 6 additions & 0 deletions modules/multi-runner/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -718,3 +718,9 @@ variable "user_agent" {
type = string
default = "github-aws-runners"
}

variable "parameter_store_tags" {
description = "Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function."
type = map(string)
default = {}
}
1 change: 1 addition & 0 deletions modules/runners/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ yarn run dist
| <a name="input_metrics"></a> [metrics](#input\_metrics) | Configuration for metrics created by the module, by default metrics are disabled to avoid additional costs. When metrics are enable all metrics are created unless explicit configured otherwise. | <pre>object({<br/> enable = optional(bool, false)<br/> namespace = optional(string, "GitHub Runners")<br/> metric = optional(object({<br/> enable_github_app_rate_limit = optional(bool, true)<br/> enable_job_retry = optional(bool, true)<br/> enable_spot_termination_warning = optional(bool, true)<br/> }), {})<br/> })</pre> | `{}` | no |
| <a name="input_minimum_running_time_in_minutes"></a> [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated if non busy. If not set the default is calculated based on the OS. | `number` | `null` | no |
| <a name="input_overrides"></a> [overrides](#input\_overrides) | This map provides the possibility to override some defaults. The following attributes are supported: `name_sg` overrides the `Name` tag for all security groups created by this module. `name_runner_agent_instance` overrides the `Name` tag for the ec2 instance defined in the auto launch configuration. `name_docker_machine_runners` overrides the `Name` tag spot instances created by the runner agent. | `map(string)` | <pre>{<br/> "name_runner": "",<br/> "name_sg": ""<br/>}</pre> | no |
| <a name="input_parameter_store_tags"></a> [parameter\_store\_tags](#input\_parameter\_store\_tags) | Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function. | `map(string)` | `{}` | no |
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. Use `schedule_expression_timezone ` to override the schedule time zone (defaults to UTC). | <pre>list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = optional(string)<br/> size = number<br/> }))</pre> | `[]` | no |
| <a name="input_pool_lambda_memory_size"></a> [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Lambda Memory size limit in MB for pool lambda | `number` | `512` | no |
| <a name="input_pool_lambda_reserved_concurrent_executions"></a> [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no |
Expand Down
5 changes: 5 additions & 0 deletions modules/runners/local.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
locals {
parameter_store_tags = "[${join(", ", [
for key, value in var.parameter_store_tags : "{ key = \"${key}\", value = \"${value}\" }"
])}]"
}
1 change: 1 addition & 0 deletions modules/runners/pool.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ module "pool" {
runtime = var.lambda_runtime
timeout = var.pool_lambda_timeout
zip = local.lambda_zip
parameter_store_tags = local.parameter_store_tags
}
pool = var.pool_config
role_path = local.role_path
Expand Down
2 changes: 1 addition & 1 deletion modules/runners/pool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ No modules.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aws_partition"></a> [aws\_partition](#input\_aws\_partition) | (optional) partition for the arn if not 'aws' | `string` | `"aws"` | no |
| <a name="input_config"></a> [config](#input\_config) | Lookup details in parent module. | <pre>object({<br/> lambda = object({<br/> log_level = string<br/> logging_retention_in_days = number<br/> logging_kms_key_id = string<br/> reserved_concurrent_executions = number<br/> s3_bucket = string<br/> s3_key = string<br/> s3_object_version = string<br/> security_group_ids = list(string)<br/> runtime = string<br/> architecture = string<br/> memory_size = number<br/> timeout = number<br/> zip = string<br/> subnet_ids = list(string)<br/> })<br/> tags = map(string)<br/> ghes = object({<br/> url = string<br/> ssl_verify = string<br/> })<br/> github_app_parameters = object({<br/> key_base64 = map(string)<br/> id = map(string)<br/> })<br/> subnet_ids = list(string)<br/> runner = object({<br/> disable_runner_autoupdate = bool<br/> ephemeral = bool<br/> enable_jit_config = bool<br/> enable_on_demand_failover_for_errors = list(string)<br/> boot_time_in_minutes = number<br/> labels = list(string)<br/> launch_template = object({<br/> name = string<br/> })<br/> group_name = string<br/> name_prefix = string<br/> pool_owner = string<br/> role = object({<br/> arn = string<br/> })<br/> })<br/> instance_types = list(string)<br/> instance_target_capacity_type = string<br/> instance_allocation_strategy = string<br/> instance_max_spot_price = string<br/> prefix = string<br/> pool = list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = string<br/> size = number<br/> }))<br/> role_permissions_boundary = string<br/> kms_key_arn = string<br/> ami_kms_key_arn = string<br/> ami_id_ssm_parameter_arn = string<br/> role_path = string<br/> ssm_token_path = string<br/> ssm_config_path = string<br/> ami_id_ssm_parameter_name = string<br/> ami_id_ssm_parameter_read_policy_arn = string<br/> arn_ssm_parameters_path_config = string<br/> lambda_tags = map(string)<br/> user_agent = string<br/> })</pre> | n/a | yes |
| <a name="input_config"></a> [config](#input\_config) | Lookup details in parent module. | <pre>object({<br/> lambda = object({<br/> log_level = string<br/> logging_retention_in_days = number<br/> logging_kms_key_id = string<br/> reserved_concurrent_executions = number<br/> s3_bucket = string<br/> s3_key = string<br/> s3_object_version = string<br/> security_group_ids = list(string)<br/> runtime = string<br/> architecture = string<br/> memory_size = number<br/> timeout = number<br/> zip = string<br/> subnet_ids = list(string)<br/> parameter_store_tags = string<br/> })<br/> tags = map(string)<br/> ghes = object({<br/> url = string<br/> ssl_verify = string<br/> })<br/> github_app_parameters = object({<br/> key_base64 = map(string)<br/> id = map(string)<br/> })<br/> subnet_ids = list(string)<br/> runner = object({<br/> disable_runner_autoupdate = bool<br/> ephemeral = bool<br/> enable_jit_config = bool<br/> enable_on_demand_failover_for_errors = list(string)<br/> boot_time_in_minutes = number<br/> labels = list(string)<br/> launch_template = object({<br/> name = string<br/> })<br/> group_name = string<br/> name_prefix = string<br/> pool_owner = string<br/> role = object({<br/> arn = string<br/> })<br/> })<br/> instance_types = list(string)<br/> instance_target_capacity_type = string<br/> instance_allocation_strategy = string<br/> instance_max_spot_price = string<br/> prefix = string<br/> pool = list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = string<br/> size = number<br/> }))<br/> role_permissions_boundary = string<br/> kms_key_arn = string<br/> ami_kms_key_arn = string<br/> ami_id_ssm_parameter_arn = string<br/> role_path = string<br/> ssm_token_path = string<br/> ssm_config_path = string<br/> ami_id_ssm_parameter_name = string<br/> ami_id_ssm_parameter_read_policy_arn = string<br/> arn_ssm_parameters_path_config = string<br/> lambda_tags = map(string)<br/> user_agent = string<br/> })</pre> | n/a | yes |
| <a name="input_tracing_config"></a> [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. | <pre>object({<br/> mode = optional(string, null)<br/> capture_http_requests = optional(bool, false)<br/> capture_error = optional(bool, false)<br/> })</pre> | `{}` | no |

## Outputs
Expand Down
1 change: 1 addition & 0 deletions modules/runners/pool/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ resource "aws_lambda_function" "pool" {
POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests
POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error
ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS = jsonencode(var.config.runner.enable_on_demand_failover_for_errors)
SSM_PARAMETER_STORE_TAGS = var.config.lambda.parameter_store_tags
}
}

Expand Down
1 change: 1 addition & 0 deletions modules/runners/pool/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ variable "config" {
timeout = number
zip = string
subnet_ids = list(string)
parameter_store_tags = string
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

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

The type for parameter_store_tags should be map(string) to match the variable definition in other modules, not string.

Suggested change
parameter_store_tags = string
parameter_store_tags = map(string)

Copilot uses AI. Check for mistakes.
})
tags = map(string)
ghes = object({
Expand Down
1 change: 1 addition & 0 deletions modules/runners/scale-up.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ resource "aws_lambda_function" "scale_up" {
POWERTOOLS_SERVICE_NAME = "runners-scale-up"
SSM_TOKEN_PATH = local.token_path
SSM_CONFIG_PATH = "${var.ssm_paths.root}/${var.ssm_paths.config}"
SSM_PARAMETER_STORE_TAGS = local.parameter_store_tags
SUBNET_IDS = join(",", var.subnet_ids)
ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS = jsonencode(var.enable_on_demand_failover_for_errors)
JOB_RETRY_CONFIG = jsonencode(local.job_retry_config)
Expand Down
6 changes: 6 additions & 0 deletions modules/runners/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -770,3 +770,9 @@ variable "user_agent" {
type = string
default = null
}

variable "parameter_store_tags" {
description = "Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function."
type = map(string)
default = {}
}
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1016,3 +1016,9 @@ variable "user_agent" {
type = string
default = "github-aws-runners"
}

variable "parameter_store_tags" {
description = "Map of tags that will be added to all the SSM Parameter Store parameters created by the Lambda function."
type = map(string)
default = {}
}
Loading