Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed


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 }[];
}

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 {
Copy link
Member

Choose a reason for hiding this comment

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

@wadherv sorry for the long wait. Just test the PR with a small adjustment. But would first discuss the intended working.

I see a fewo options, but looking for use cases.

  1. Just apply the values in var.tags to the paramters. Most simple approach.
  2. Allow users two set custom tags for the pramaters, which are applied instead of adding the defautl from var.tgas. But for this I looking for a use case.

I have adjust the this local.tf file for a quick check, optiotn 2.

locals {
  parameter_store_tags = "[${join(", ", [
    for key, value in length(var.parameter_store_tags) > 0 ? var.parameter_store_tags : var.tags : "{ key = \"${key}\", value = \"${value}\" }"
  ])}]"
}

In this case paramters got the valures from var.tags applices. Since I have not set parameter_store_tags.

What do you think. Are you looking for way have custom tags, or just getting the standard tags applices. When only adding the standard tag set in the module, we could even drop the introduced paramter (reducing complexity) and simply inject var.tags into the lambda.

Copy link
Contributor Author

@wadherv wadherv Nov 6, 2025

Choose a reason for hiding this comment

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

@npalm For my requirement, I want to apply only the default set of tags to the SSM Parameter Store, while also providing users the option to add additional custom tags specific to SSM Parameter resources.
Now that you have highlighted this, may be a better way is to merge var.tags and var.parameter_store_tags so that it work as intended(similar to https://github.com/github-aws-runners/terraform-aws-github-runner/blob/main/modules/runners/variables.tf#L716).
Let me know if this sounds reasonable, and i can make the required code changes.

Copy link
Contributor Author

@wadherv wadherv Nov 7, 2025

Choose a reason for hiding this comment

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

Something like below:
locals {
parameter_store_tags = "[${join(", ", [
for key, value in merge(var.tags, var.parameter_store_tags) : "{ key = "${key}", value = "${value}" }"
])}]"
}

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.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

})
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