Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b63131c
test: use my personal fork
edersonbrilhante Dec 15, 2025
de4a149
feat: add custom scale errors
edersonbrilhante Dec 15, 2025
0653263
feat: wire custom_scale_errors
edersonbrilhante Dec 15, 2025
c7a6bcf
feat: add more options for placement
edersonbrilhante Dec 17, 2025
aaad307
feat: add user data for osx
edersonbrilhante Dec 17, 2025
121f670
fix: fix interpolation
edersonbrilhante Dec 17, 2025
db6c149
feat: add permission ec2:DescribeHosts
edersonbrilhante Dec 17, 2025
6f8a25e
fix: fix wrong type for host_resource_group_arn
edersonbrilhante Dec 18, 2025
5a46778
fix: remove non-compatible script
edersonbrilhante Dec 18, 2025
d31ad67
test: disable user_data_osx.tftpl
edersonbrilhante Dec 18, 2025
040abc8
feat: add license_specification
edersonbrilhante Dec 18, 2025
78cce4d
fix: use list of license
edersonbrilhante Dec 18, 2025
57d0e1c
fix: rename variable
edersonbrilhante Dec 18, 2025
ac9bc12
fix: fix user data
edersonbrilhante Dec 19, 2025
470ee14
feat: add windows support
edersonbrilhante Dec 22, 2025
eeae4c1
test: use new user-data
edersonbrilhante Dec 23, 2025
5f8669d
fix: add cd in scripts
edersonbrilhante Dec 23, 2025
974381e
fix: add transcript
edersonbrilhante Dec 29, 2025
410ce1a
feat: use new branch
edersonbrilhante Jan 7, 2026
1d2739d
fix: fix typo in outputs
edersonbrilhante Jan 9, 2026
68c776d
fix: trigger gh app update when github app setting has changed
edersonbrilhante Jan 9, 2026
1813c90
chore: update ec2 lambda versions
edersonbrilhante Jan 13, 2026
e4dcf5d
feat: add support to tag karpenter nodes
edersonbrilhante Jan 16, 2026
b0c1ef4
fix: fix missing paramter in template
edersonbrilhante Jan 16, 2026
4bce20c
fix: add missing annotation
edersonbrilhante Feb 5, 2026
788419f
chore: update philips labs module
edersonbrilhante Feb 5, 2026
67dd48a
feat: use input to tag ssm
edersonbrilhante Feb 5, 2026
58dd728
chore: upgrade arc
edersonbrilhante Feb 5, 2026
db11c9a
fix: use toleration and affinity
edersonbrilhante Feb 5, 2026
8105564
fix: rollback splunk_otel_collector
edersonbrilhante Feb 5, 2026
102390f
fix: undo affinity
edersonbrilhante Feb 5, 2026
aca4004
fix: use affinity
edersonbrilhante Feb 5, 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
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ locals {
min_run_time = 30
max_instances = spec.max_instances
instance_types = spec.instance_types
placement = try(spec.placement, null)
license_specifications = try(spec.license_specifications, null)
block_device_mappings = [{
delete_on_termination = true
device_name = spec.volume.device_name
Expand Down
2 changes: 2 additions & 0 deletions examples/templates/tenant/tenant/runner_settings.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ locals {
min_run_time = 30
max_instances = spec.max_instances
instance_types = spec.instance_types
placement = try(spec.placement, null)
license_specifications = try(spec.license_specifications, null)
block_device_mappings = [{
delete_on_termination = true
device_name = spec.volume.device_name
Expand Down
8 changes: 7 additions & 1 deletion modules/core/arc/karpenter.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ locals {
})

kubeconfig_path = "${path.cwd}/.kube/${var.eks_cluster_name}-${var.aws_profile}-${var.aws_region}-${var.controller_config.namespace}.kubeconfig"

merged_tags = merge(
var.tags,
{
Name = "${var.eks_cluster_name}-karpenter-${var.controller_config.namespace}-node"
})
}

data "external" "update_kubeconfig" {
Expand Down Expand Up @@ -51,7 +57,7 @@ data "external" "karpenter_ec2nodeclass" {
)
' - \
| yq eval -o=json - \
| jq --argjson newtags '${jsonencode(var.tags)}' --arg newname "karpenter-${var.controller_config.namespace}" '
| jq --argjson newtags '${jsonencode(local.merged_tags)}' --arg newname "karpenter-${var.controller_config.namespace}" '
.spec.tags = (.spec.tags // {}) |
.spec.tags *= $newtags |
.metadata.name = $newname
Expand Down
7 changes: 7 additions & 0 deletions modules/core/arc/scale_set/template_files/dind.yml.tftpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ runnerGroup: "${runner_group_name}"
runnerScaleSetName: "${scale_set_name}"

template:
metadata:
annotations:
karpenter.sh/do-not-disrupt: "true"
spec:
serviceAccountName: ${service_account}
automountServiceAccountToken: true
Expand Down Expand Up @@ -252,6 +255,7 @@ template:
audience: sts.amazonaws.com

tolerations:
# tenant tolerations
- key: "forge.local/scale_set_type"
operator: "Equal"
value: "dind"
Expand All @@ -266,6 +270,7 @@ template:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
# tenant affinity
- key: forge.local/scale_set_type
operator: In
values:
Expand All @@ -274,6 +279,8 @@ template:
operator: In
values:
- ${tenant}
- key: "karpenter.sh/disrupted"
operator: DoesNotExist

controllerServiceAccount:
namespace: ${controller_namespace}
Expand Down
11 changes: 10 additions & 1 deletion modules/core/arc/scale_set/template_files/k8s.yml.tftpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ containerMode:
template:
metadata:
annotations:
karpenter.sh/do-not-evict: "true"
karpenter.sh/do-not-disrupt: "true"
spec:
securityContext:
fsGroup: 123
Expand Down Expand Up @@ -136,6 +136,15 @@ template:
configMap:
name: hook-pre-post-job-${scale_set_name}

affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
# karpenter affinity
- key: "karpenter.sh/disrupted"
operator: DoesNotExist

controllerServiceAccount:
namespace: ${controller_namespace}
name: ${controller_service_account}
1 change: 1 addition & 0 deletions modules/infra/eks/karpenter.tf
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ locals {
disk_type = var.cluster_volume.type
disk_iops = var.cluster_volume.iops
disk_throughput = var.cluster_volume.throughput
cluster_name = var.cluster_name
})

node_pool_manifest = templatefile("${path.module}/templates/node_pool.yaml.tpl", {
Expand Down
1 change: 1 addition & 0 deletions modules/infra/eks/templates/ec2_node_class.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ spec:
%{ for k, v in tags }
${k}: '${v}'
%{ endfor }
Name: '${cluster_name}-karpenter-shared-node'
1 change: 1 addition & 0 deletions modules/infra/forge_subscription/policies.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ data "aws_iam_policy_document" "packer_support_for_forge_runners" {
"ec2:DeleteSnapshot",
"ec2:DeleteVolume",
"ec2:DeregisterImage",
"ec2:DescribeHosts",
"ec2:DescribeImageAttribute",
"ec2:DescribeImages",
"ec2:DescribeInstanceStatus",
Expand Down
2 changes: 1 addition & 1 deletion modules/integrations/splunk_otel_eks/otel.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ resource "helm_release" "splunk_otel_collector" {
name = "splunk-otel-collector"
repository = "https://signalfx.github.io/splunk-otel-collector-chart"
chart = "splunk-otel-collector"
version = "0.143.0"
version = "0.141.0"
namespace = "splunk-otel-collector"
create_namespace = true

Expand Down
2 changes: 1 addition & 1 deletion modules/platform/arc_deployment/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module "arc" {
release_name = var.runner_configs.prefix
namespace = var.tenant_configs.name
chart_name = "oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller"
chart_version = "0.13.0"
chart_version = "0.13.1"
name = "${var.runner_configs.prefix}-gha-rs-controller"
}

Expand Down
81 changes: 49 additions & 32 deletions modules/platform/ec2_deployment/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ locals {
# Templatized userdata (cloud-init) file.
user_data_prefix = "${path.module}/template_files"
userdata_template_post_install = "${local.user_data_prefix}/post_install.tftpl"
user_data_template_runner = "${local.user_data_prefix}/user_data.tftpl"
runner_template_hook_job_started = "${local.user_data_prefix}/hook_job_started.tftpl"
runner_template_hook_job_completed = "${local.user_data_prefix}/hook_job_completed.tftpl"

Expand Down Expand Up @@ -35,11 +34,12 @@ data "aws_subnet" "runner_subnet" {
}

data "external" "download_lambdas" {
program = ["bash", "${path.module}/scripts/download_lambdas.sh", "/tmp/${var.runner_configs.prefix}/", "v7.3.0"]
program = ["bash", "${path.module}/scripts/download_lambdas.sh", "/tmp/${var.runner_configs.prefix}/", "v7.4.0"]
}


module "runners" {
source = "git::https://github.com/github-aws-runners/terraform-aws-github-runner.git//modules/multi-runner?ref=v7.3.0"
source = "git::https://github.com/edersonbrilhante/terraform-aws-github-runner.git//modules/multi-runner?ref=feat-macos-support"

aws_region = var.aws_region

Expand All @@ -58,8 +58,9 @@ module "runners" {
enable = true
}

lambda_tags = var.tenant_configs.tags
tags = var.tenant_configs.tags
lambda_tags = var.tenant_configs.tags
tags = var.tenant_configs.tags
parameter_store_tags = var.tenant_configs.tags

# Verbose logging.
log_level = var.runner_configs.log_level
Expand Down Expand Up @@ -116,7 +117,8 @@ module "runners" {
runner_group_name = var.runner_configs.runner_group_name
enable_runner_binaries_syncer = false
enable_userdata = val["enable_userdata"]
userdata_template = local.user_data_template_runner
scale_errors = var.runner_configs.scale_errors
userdata_template = "${local.user_data_prefix}/user_data_${val["runner_os"]}.tftpl"
userdata_pre_install = "# No pre-install steps."
userdata_post_install = templatefile(
local.userdata_template_post_install,
Expand All @@ -130,33 +132,46 @@ module "runners" {
enable_runner_detailed_monitoring = true
runner_run_as = val["runner_user"]
block_device_mappings = val["block_device_mappings"]
license_specifications = val["license_specifications"]
placement = val["placement"]
runner_log_files = [
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/var/log/syslog",
"log_stream_name" : "{instance_id}/syslog"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/var/log/user-data.log",
"log_stream_name" : "{instance_id}/user-data"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/opt/actions-runner/_diag/Runner_**.log",
"log_stream_name" : "{instance_id}/runner"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/home/${val["runner_user"]}/hook.log",
"log_stream_name" : "{instance_id}/hook"
},
]
runner_log_files = concat(
// Linux/macOS-only logs
val["runner_os"] == "windows" ? [] : [
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/var/log/syslog",
"log_stream_name" : "{instance_id}/syslog"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/home/${val["runner_user"]}/hook.log",
"log_stream_name" : "{instance_id}/hook"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : "/home/${val["runner_user"]}/hook.log",
"log_stream_name" : "{instance_id}/hook"
},
],
// Logs that exist on all OSes, with OS-specific paths
[
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : val["runner_os"] == "windows" ? "C:/UserData.log" : "/var/log/user-data.log",
"log_stream_name" : "{instance_id}/user-data"
},
{
"log_group_name" : "forge-logs",
"prefix_log_group" : true,
"file_path" : val["runner_os"] == "windows" ? "C:/actions-runner/_diag/Runner_*.log" : "/opt/actions-runner/_diag/Runner_**.log",
"log_stream_name" : "{instance_id}/runner"
},
],
)
ami = {
owners = val["ami_owners"]
filter = val["ami_filter"]
Expand All @@ -170,6 +185,8 @@ module "runners" {
aws_iam_policy.ec2_tags.arn,
]
)
vpc_id = val["vpc_id"]
subnet_ids = val["subnet_ids"]
enable_ephemeral_runners = true
create_service_linked_role_spot = true
enable_organization_runners = true
Expand Down
27 changes: 27 additions & 0 deletions modules/platform/ec2_deployment/template_files/user_data_osx.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

set +x
%{ if enable_debug_logging }
set -x
%{ endif }

# Just a dummy value (user-supplied string; does nothing).
${pre_install}

# Set defaults for macOS EC2 instances.
# Default user on EC2 macOS AMIs is typically "ec2-user".
user_name=ec2-user

touch .env
chmod 0644 .env

grep -q "^PATH=" .env || echo "PATH=$PATH" >> .env

# Configure CloudWatch logging agent if installed and configured for macOS.
if command -v /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl >/dev/null 2>&1; then
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c ssm:${ssm_key_cloudwatch_agent_config} || true
fi

cd /opt/actions-runner

${start_runner}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<powershell>

$logPath = 'C:\UserData.log'

Start-Transcript -Path $logPath -Append

$ssm = Get-Service AmazonSSMAgent -ErrorAction SilentlyContinue
if ($ssm) {
Set-Service AmazonSSMAgent -StartupType Automatic
if ($ssm.Status -ne 'Running') {
Start-Service AmazonSSMAgent
}
}

${pre_install}

Set-Location C:\actions-runner

${start_runner}

Stop-Transcript

</powershell>
16 changes: 15 additions & 1 deletion modules/platform/ec2_deployment/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ variable "runner_configs" {
})
runner_iam_role_managed_policy_arns = list(string)
runner_group_name = string
scale_errors = optional(list(string), [])
runner_specs = map(object({
ami_filter = object({
name = list(string)
Expand All @@ -32,8 +33,19 @@ variable "runner_configs" {
max_instances = number
min_run_time = number
instance_types = list(string)
license_specifications = optional(list(object({
license_configuration_arn = string
})), null)
placement = optional(object({
host_id = optional(string, null)
affinity = optional(string)
availability_zone = optional(string)
group_id = optional(string)
group_name = optional(string)
host_id = optional(string)
host_resource_group_arn = optional(string)
spread_domain = optional(string)
tenancy = optional(string)
partition_number = optional(number)
}), null)
pool_config = list(object({
size = number
Expand All @@ -43,6 +55,8 @@ variable "runner_configs" {
runner_user = string
enable_userdata = bool
instance_target_capacity_type = string
vpc_id = optional(string, null)
subnet_ids = optional(list(string), null)
block_device_mappings = list(object({
delete_on_termination = bool
device_name = string
Expand Down
1 change: 1 addition & 0 deletions modules/platform/forge_runners/ec2_runners.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module "ec2_runners" {
webhook_secret = aws_ssm_parameter.github_app_webhook_secret.value
}
runner_group_name = var.deployment_config.github.runner_group_name
scale_errors = var.ec2_deployment_specs.scale_errors
runner_specs = var.ec2_deployment_specs.runner_specs
}
}
2 changes: 1 addition & 1 deletion modules/platform/forge_runners/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ locals {
]
)

github_app_installation = "${var.deployment_config.github.ghes_url == "" ? "https://github.com" : var.deployment_config.github.ghes_url}/apps/${var.deployment_config.github_app.name}}/installations/${var.deployment_config.github_app.installation_id}"
github_app_installation = "${var.deployment_config.github.ghes_url == "" ? "https://github.com" : var.deployment_config.github.ghes_url}/apps/${var.deployment_config.github_app.name}/installations/${var.deployment_config.github_app.installation_id}"
github_api = var.deployment_config.github.ghes_url == "" ? "https://api.github.com" : "https://api.${replace(var.deployment_config.github.ghes_url, "https://", "")}"
}
14 changes: 9 additions & 5 deletions modules/platform/forge_runners/update_gh_app.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
resource "null_resource" "update_github_app_webhook" {
triggers = {
ghes_org = var.deployment_config.github.ghes_org
ghes_url = var.deployment_config.github.ghes_url
webhook_url = try(module.ec2_runners[0].webhook_endpoint, "https://cisco-open.github.io/forge")
secret = aws_ssm_parameter.github_app_webhook_secret.value
secret_version = aws_ssm_parameter.github_app_webhook_secret.version
ghes_org = var.deployment_config.github.ghes_org
ghes_url = var.deployment_config.github.ghes_url
webhook_url = try(module.ec2_runners[0].webhook_endpoint, "https://cisco-open.github.io/forge")
secret = aws_ssm_parameter.github_app_webhook_secret.value
secret_version = aws_ssm_parameter.github_app_webhook_secret.version
id = var.deployment_config.github_app.id
client_id = var.deployment_config.github_app.client_id
installation_id = var.deployment_config.github_app.installation_id
name = var.deployment_config.github_app.name
}

provisioner "local-exec" {
Expand Down
Loading