Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
bfcc988
feat: add support to use custom scale errors
edersonbrilhante Dec 4, 2025
a616376
chore: update variable description
edersonbrilhante Dec 4, 2025
1c3b579
fix: fix typo
edersonbrilhante Dec 4, 2025
0e433c2
style: fix ts formating
edersonbrilhante Dec 4, 2025
a797a0c
docs: auto update terraform docs
github-actions[bot] Dec 15, 2025
42d4df8
style: fix formatting issue
edersonbrilhante Dec 15, 2025
e5536da
test: fix test after rebase
edersonbrilhante Dec 15, 2025
3f3981c
fix: missing property in NodeJS
edersonbrilhante Dec 16, 2025
dc6e8d8
refactor: remove custom friom variable and add default values
edersonbrilhante Dec 18, 2025
0f7645f
feat: add osx options
edersonbrilhante Dec 3, 2025
92fe748
feat: create runner scripts for macos
edersonbrilhante Dec 3, 2025
10a0da6
docs: auto update terraform docs
github-actions[bot] Dec 15, 2025
e47c8a5
fix: remove not needed variable
edersonbrilhante Dec 17, 2025
27a91a6
fix: fix ownership group
edersonbrilhante Dec 18, 2025
20e611e
fix: fix wrong type for host_resource_group_arn
edersonbrilhante Dec 18, 2025
cf4e3e3
feat: add license_specification
edersonbrilhante Dec 18, 2025
5586b38
fix: use list of license_specification
edersonbrilhante Dec 18, 2025
112804b
fix: fix typo
edersonbrilhante Dec 18, 2025
faa4de5
docs: add example to create dedicate hosts and host group
edersonbrilhante Dec 22, 2025
fea21d6
fix: fix install runner for windows
edersonbrilhante Dec 23, 2025
ac96589
fix: remove cd in start
edersonbrilhante Dec 23, 2025
699e252
fix: undo windows change
edersonbrilhante Jan 7, 2026
68e4bb9
docs: fix typo
edersonbrilhante Jan 7, 2026
5b84e22
docs: auto update terraform docs
github-actions[bot] Jan 13, 2026
94609f6
fix: fix github copilot findings
edersonbrilhante Jan 14, 2026
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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Join our discord community via [this invite link](https://discord.gg/bxgXW8jJGh)
| <a name="input_instance_profile_path"></a> [instance\_profile\_path](#input\_instance\_profile\_path) | The path that will be added to the instance\_profile, if not set the environment name will be used. | `string` | `null` | no |
| <a name="input_instance_target_capacity_type"></a> [instance\_target\_capacity\_type](#input\_instance\_target\_capacity\_type) | Default lifecycle used for runner instances, can be either `spot` or `on-demand`. | `string` | `"spot"` | no |
| <a name="input_instance_termination_watcher"></a> [instance\_termination\_watcher](#input\_instance\_termination\_watcher) | Configuration for the instance termination watcher. This feature is Beta, changes will not trigger a major release as long in beta.<br/><br/>`enable`: Enable or disable the spot termination watcher.<br/>'features': Enable or disable features of the termination watcher.<br/>`memory_size`: Memory size limit in MB of the lambda.<br/>`s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas.<br/>`s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket.<br/>`timeout`: Time out of the lambda in seconds.<br/>`zip`: File location of the lambda zip file. | <pre>object({<br/> enable = optional(bool, false)<br/> features = optional(object({<br/> enable_spot_termination_handler = optional(bool, true)<br/> enable_spot_termination_notification_watcher = optional(bool, true)<br/> }), {})<br/> memory_size = optional(number, null)<br/> s3_key = optional(string, null)<br/> s3_object_version = optional(string, null)<br/> timeout = optional(number, null)<br/> zip = optional(string, null)<br/> })</pre> | `{}` | no |
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (al2023 for linux and Windows Server Core for win). | `list(string)` | <pre>[<br/> "m5.large",<br/> "c5.large"<br/>]</pre> | no |
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (al2023 for linux, macOS Sequoia for osx, Windows Server Core for win). | `list(string)` | <pre>[<br/> "m5.large",<br/> "c5.large"<br/>]</pre> | no |
| <a name="input_job_queue_retention_in_seconds"></a> [job\_queue\_retention\_in\_seconds](#input\_job\_queue\_retention\_in\_seconds) | The number of seconds the job is held in the queue before it is purged. | `number` | `86400` | no |
| <a name="input_job_retry"></a> [job\_retry](#input\_job\_retry) | Experimental! Can be removed / changed without trigger a major release.Configure job retries. The configuration enables job retries (for ephemeral runners). After creating the instances a message will be published to a job retry queue. The job retry check lambda is checking after a delay if the job is queued. If not the message will be published again on the scale-up (build queue). Using this feature can impact the rate limit of the GitHub app.<br/><br/>`enable`: Enable or disable the job retry feature.<br/>`delay_in_seconds`: The delay in seconds before the job retry check lambda will check the job status.<br/>`delay_backoff`: The backoff factor for the delay.<br/>`lambda_memory_size`: Memory size limit in MB for the job retry check lambda.<br/>`lambda_timeout`: Time out of the job retry check lambda in seconds.<br/>`max_attempts`: The maximum number of attempts to retry the job. | <pre>object({<br/> enable = optional(bool, false)<br/> delay_in_seconds = optional(number, 300)<br/> delay_backoff = optional(number, 2)<br/> lambda_memory_size = optional(number, 256)<br/> lambda_timeout = optional(number, 30)<br/> max_attempts = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_key_name"></a> [key\_name](#input\_key\_name) | Key pair name | `string` | `null` | no |
Expand Down Expand Up @@ -196,10 +196,11 @@ Join our discord community via [this invite link](https://discord.gg/bxgXW8jJGh)
| <a name="input_runner_hook_job_completed"></a> [runner\_hook\_job\_completed](#input\_runner\_hook\_job\_completed) | Script to be ran in the runner environment at the end of every job | `string` | `""` | no |
| <a name="input_runner_hook_job_started"></a> [runner\_hook\_job\_started](#input\_runner\_hook\_job\_started) | Script to be ran in the runner environment at the beginning of every job | `string` | `""` | no |
| <a name="input_runner_iam_role_managed_policy_arns"></a> [runner\_iam\_role\_managed\_policy\_arns](#input\_runner\_iam\_role\_managed\_policy\_arns) | Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role | `list(string)` | `[]` | no |
| <a name="input_runner_license_specifications"></a> [runner\_license\_specifications](#input\_runner\_license\_specifications) | The license specifications for the instance. See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#license_specification for details. | <pre>list(object({<br/> license_configuration_arn = string<br/> }))</pre> | `[]` | no |
| <a name="input_runner_log_files"></a> [runner\_log\_files](#input\_runner\_log\_files) | (optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. | <pre>list(object({<br/> log_group_name = string<br/> prefix_log_group = bool<br/> file_path = string<br/> log_stream_name = string<br/> }))</pre> | `null` | no |
| <a name="input_runner_metadata_options"></a> [runner\_metadata\_options](#input\_runner\_metadata\_options) | Metadata options for the ec2 runner instances. By default, the module uses metadata tags for bootstrapping the runner, only disable `instance_metadata_tags` when using custom scripts for starting the runner. | `map(any)` | <pre>{<br/> "http_endpoint": "enabled",<br/> "http_put_response_hop_limit": 1,<br/> "http_tokens": "required",<br/> "instance_metadata_tags": "enabled"<br/>}</pre> | no |
| <a name="input_runner_name_prefix"></a> [runner\_name\_prefix](#input\_runner\_name\_prefix) | The prefix used for the GitHub runner name. The prefix will be used in the default start script to prefix the instance name when register the runner in GitHub. The value is available via an EC2 tag 'ghr:runner\_name\_prefix'. | `string` | `""` | no |
| <a name="input_runner_os"></a> [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no |
| <a name="input_runner_os"></a> [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no |
| <a name="input_runner_placement"></a> [runner\_placement](#input\_runner\_placement) | The placement options for the instance. See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#placement for details. | <pre>object({<br/> affinity = optional(string)<br/> availability_zone = optional(string)<br/> group_id = optional(string)<br/> group_name = optional(string)<br/> host_id = optional(string)<br/> host_resource_group_arn = optional(string)<br/> spread_domain = optional(string)<br/> tenancy = optional(string)<br/> partition_number = optional(number)<br/> })</pre> | `null` | no |
| <a name="input_runner_run_as"></a> [runner\_run\_as](#input\_runner\_run\_as) | Run the GitHub actions agent as user. | `string` | `"ec2-user"` | no |
| <a name="input_runners_ebs_optimized"></a> [runners\_ebs\_optimized](#input\_runners\_ebs\_optimized) | Enable EBS optimization for the runner instances. | `bool` | `false` | no |
Expand Down
42 changes: 42 additions & 0 deletions examples/dedicated-mac-hosts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.21 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.21 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_ec2_host.mac_dedicated_host](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_host) | resource |
| [aws_licensemanager_license_configuration.mac_dedicated_host_license_configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/licensemanager_license_configuration) | resource |
| [aws_resourcegroups_group.mac_host_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource |
| [aws_resourcegroups_resource.mac_host_membership](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_resource) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes |
| <a name="input_environment"></a> [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no |
| <a name="input_host_groups"></a> [host\_groups](#input\_host\_groups) | Map of host groups, each with a name, host instance type, and a list of hosts (name + AZ). | <pre>map(object({<br/> name = string<br/> host_instance_type = string<br/> hosts = list(object({<br/> name = string<br/> availability_zone = string<br/> }))<br/> }))</pre> | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_license_specification_arn"></a> [license\_specification\_arn](#output\_license\_specification\_arn) | ARN of the License Manager configuration used for Mac dedicated hosts. |
| <a name="output_resource_group_arns"></a> [resource\_group\_arns](#output\_resource\_group\_arns) | Map of resource group names to their ARNs. |
<!-- END_TF_DOCS -->
105 changes: 105 additions & 0 deletions examples/dedicated-mac-hosts/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
locals {

environment = var.environment != null ? var.environment : "default"
aws_region = var.aws_region

# Flatten host_groups into a map of individual host definitions keyed by
# "groupKey-hostName" so we can create one aws_ec2_host per host.
mac_dedicated_hosts = merge([
for group_key, group in var.host_groups : {
for host in group.hosts :
"${group_key}-${host.name}" => {
instance_type = group.host_instance_type
availability_zone = host.availability_zone
group_name = group.name
host_name = host.name
}
}
]...)
}

resource "aws_ec2_host" "mac_dedicated_host" {
for_each = local.mac_dedicated_hosts

instance_type = each.value.instance_type
availability_zone = each.value.availability_zone
auto_placement = "on"

tags = {
"Name" = each.value.host_name
"HostGroup" = each.value.group_name
}
}

resource "aws_resourcegroups_group" "mac_host_group" {
for_each = { for _, group in var.host_groups : group.name => group }

name = each.value.name

configuration {
type = "AWS::EC2::HostManagement"

parameters {
name = "any-host-based-license-configuration"
values = ["true"]
}

parameters {
name = "auto-allocate-host"
values = [
"false",
]
}
parameters {
name = "auto-host-recovery"
values = [
"false",
]
}
parameters {
name = "auto-release-host"
values = [
"false",
]
}
}

configuration {
type = "AWS::ResourceGroups::Generic"
parameters {
name = "allowed-resource-types"
values = [
"AWS::EC2::Host",
]
}

parameters {
name = "deletion-protection"
values = [
"UNLESS_EMPTY",
]
}
}

tags = {
"Name" = each.value.name
}
}

resource "aws_resourcegroups_resource" "mac_host_membership" {
for_each = local.mac_dedicated_hosts

group_arn = aws_resourcegroups_group.mac_host_group[each.value.group_name].arn
resource_arn = aws_ec2_host.mac_dedicated_host[each.key].arn
}


resource "aws_licensemanager_license_configuration" "mac_dedicated_host_license_configuration" {
name = "mac-dedicated-host-license-configuration"
description = "Mac dedicated host license configuration"
license_counting_type = "Socket"

tags = {
"Name" = "mac-dedicated-host-license-configuration"
}
}
12 changes: 12 additions & 0 deletions examples/dedicated-mac-hosts/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
output "resource_group_arns" {
description = "Map of resource group names to their ARNs."
value = {
for k, rg in aws_resourcegroups_group.mac_host_group :
rg.name => rg.arn
}
}

output "license_specification_arn" {
description = "ARN of the License Manager configuration used for Mac dedicated hosts."
value = aws_licensemanager_license_configuration.mac_dedicated_host_license_configuration.arn
}
9 changes: 9 additions & 0 deletions examples/dedicated-mac-hosts/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
provider "aws" {
region = local.aws_region

default_tags {
tags = {
Example = local.environment
}
}
}
23 changes: 23 additions & 0 deletions examples/dedicated-mac-hosts/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
variable "aws_region" {
description = "AWS region."
type = string
}

variable "environment" {
description = "Environment name, used as prefix."

type = string
default = null
}

variable "host_groups" {
description = "Map of host groups, each with a name, host instance type, and a list of hosts (name + AZ)."
type = map(object({
name = string
host_instance_type = string
hosts = list(object({
name = string
availability_zone = string
}))
}))
}
10 changes: 10 additions & 0 deletions examples/dedicated-mac-hosts/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.21"
}
}

required_version = ">= 1.3.0"
}
2 changes: 1 addition & 1 deletion examples/prebuilt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ terraform output webhook_secret
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no |
| <a name="input_github_app"></a> [github\_app](#input\_github\_app) | GitHub for API usages. | <pre>object({<br/> id = string<br/> key_base64 = string<br/> })</pre> | n/a | yes |
| <a name="input_runner_os"></a> [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no |
| <a name="input_runner_os"></a> [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no |

## Outputs

Expand Down
2 changes: 1 addition & 1 deletion examples/prebuilt/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ variable "aws_region" {
}

variable "runner_os" {
description = "The EC2 Operating System type to use for action runner instances (linux,windows)."
description = "The EC2 Operating System type to use for action runner instances (linux, osx, windows)."

type = string
default = "linux"
Expand Down
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ module "runners" {
credit_specification = var.runner_credit_specification
cpu_options = var.runner_cpu_options
placement = var.runner_placement
license_specifications = var.runner_license_specifications

enable_runner_binaries_syncer = var.enable_runner_binaries_syncer
lambda_s3_bucket = var.lambda_s3_bucket
Expand Down
2 changes: 1 addition & 1 deletion 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 @@ -56,6 +56,7 @@ module "runners" {
credit_specification = each.value.runner_config.credit_specification
cpu_options = each.value.runner_config.cpu_options
placement = each.value.runner_config.placement
license_specifications = each.value.runner_config.license_specifications

enable_runner_binaries_syncer = each.value.runner_config.enable_runner_binaries_syncer
lambda_s3_bucket = var.lambda_s3_bucket
Expand Down
7 changes: 5 additions & 2 deletions modules/multi-runner/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ variable "multi_runner_config" {
tenancy = optional(string)
partition_number = optional(number)
}), null)
license_specifications = optional(list(object({
license_configuration_arn = string
})), [])
runner_log_files = optional(list(object({
log_group_name = string
prefix_log_group = bool
Expand Down Expand Up @@ -196,7 +199,7 @@ variable "multi_runner_config" {
description = <<EOT
multi_runner_config = {
runner_config: {
runner_os: "The EC2 Operating System type to use for action runner instances (linux,windows)."
runner_os: "The EC2 Operating System type to use for action runner instances (linux, osx, windows)."
runner_architecture: "The platform architecture of the runner instance_type."
runner_metadata_options: "(Optional) Metadata options for the ec2 runner instances."
ami: "(Optional) AMI configuration for the action runner instances. This object allows you to specify all AMI-related settings in one place."
Expand All @@ -216,7 +219,7 @@ variable "multi_runner_config" {
instance_allocation_strategy: "The allocation strategy for spot instances. AWS recommends to use `capacity-optimized` however the AWS default is `lowest-price`."
instance_max_spot_price: "Max price price for spot instances per hour. This variable will be passed to the create fleet as max spot price for the fleet."
instance_target_capacity_type: "Default lifecycle used for runner instances, can be either `spot` or `on-demand`."
instance_types: "List of instance types for the action runner. Defaults are based on runner_os (al2023 for linux and Windows Server Core for win)."
instance_types: "List of instance types for the action runner. Defaults are based on runner_os (al2023 for linux, macOS Sequoia for osx, Windows Server Core for win)."
job_queue_retention_in_seconds: "The number of seconds the job is held in the queue before it is purged"
minimum_running_time_in_minutes: "The time an ec2 action runner should be running at minimum before terminated if not busy."
pool_runner_owner: "The pool will deploy runners to the GitHub org ID, set this value to the org to which you want the runners deployed. Repo level is not supported."
Expand Down
Loading
Loading