Skip to content
This repository was archived by the owner on Jan 16, 2025. It is now read-only.

Commit 259a852

Browse files
winwinashwingithub-actions[bot]npalm
authored
feat: Natively support runner pre/post job hooks (#4263)
Adds two optional string arguments to the module - `runner_hook_job_started` - `runner_hook_job_completed` If not empty, registers the hook in `user-data.sh` Ref: https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md Closes: https://github.com/philips-labs/terraform-aws-github-runner/issues/4260 Discussion: https://github.com/philips-labs/terraform-aws-github-runner/issues/3854 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Niek Palm <[email protected]> Co-authored-by: Niek Palm <[email protected]>
1 parent 401a373 commit 259a852

File tree

12 files changed

+81
-9
lines changed

12 files changed

+81
-9
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ Talk to the forestkeepers in the `runners-channel` on Slack.
210210
| <a name="input_runner_egress_rules"></a> [runner\_egress\_rules](#input\_runner\_egress\_rules) | List of egress rules for the GitHub runner instances. | <pre>list(object({<br/> cidr_blocks = list(string)<br/> ipv6_cidr_blocks = list(string)<br/> prefix_list_ids = list(string)<br/> from_port = number<br/> protocol = string<br/> security_groups = list(string)<br/> self = bool<br/> to_port = number<br/> description = string<br/> }))</pre> | <pre>[<br/> {<br/> "cidr_blocks": [<br/> "0.0.0.0/0"<br/> ],<br/> "description": null,<br/> "from_port": 0,<br/> "ipv6_cidr_blocks": [<br/> "::/0"<br/> ],<br/> "prefix_list_ids": null,<br/> "protocol": "-1",<br/> "security_groups": null,<br/> "self": null,<br/> "to_port": 0<br/> }<br/>]</pre> | no |
211211
| <a name="input_runner_extra_labels"></a> [runner\_extra\_labels](#input\_runner\_extra\_labels) | Extra (custom) labels for the runners (GitHub). Separate each label by a comma. Labels checks on the webhook can be enforced by setting `enable_workflow_job_labels_check`. GitHub read-only labels should not be provided. | `list(string)` | `[]` | no |
212212
| <a name="input_runner_group_name"></a> [runner\_group\_name](#input\_runner\_group\_name) | Name of the runner group. | `string` | `"Default"` | no |
213+
| <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 |
214+
| <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 |
213215
| <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 |
214216
| <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 |
215217
| <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 |

Diff for: examples/multi-runner/templates/runner-configs/linux-arm64.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ runner_config:
1818
runners_maximum_count: 1
1919
delay_webhook_event: 0
2020
scale_down_schedule_expression: cron(* * * * ? *)
21+
runner_hook_job_started: |
22+
echo "Running pre job hook as \$(whoami)"
23+
runner_hook_job_completed: |
24+
echo "Running post job hook as \$(whoami)"

Diff for: examples/multi-runner/templates/user-data.sh

+14
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,18 @@ ${post_install}
8181

8282
cd /opt/actions-runner
8383

84+
%{ if hook_job_started != "" }
85+
cat > /opt/actions-runner/hook_job_started.sh << EOF
86+
${hook_job_started}
87+
EOF
88+
echo ACTIONS_RUNNER_HOOK_JOB_STARTED=/opt/actions-runner/hook_job_started.sh | tee -a /opt/actions-runner/.env
89+
%{ endif }
90+
91+
%{ if hook_job_completed != "" }
92+
cat > /opt/actions-runner/hook_job_completed.sh << EOF
93+
${hook_job_completed}
94+
EOF
95+
echo ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/opt/actions-runner/hook_job_completed.sh | tee -a /opt/actions-runner/.env
96+
%{ endif }
97+
8498
${start_runner}

Diff for: main.tf

+2
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ module "runners" {
249249
userdata_content = var.userdata_content
250250
userdata_pre_install = var.userdata_pre_install
251251
userdata_post_install = var.userdata_post_install
252+
runner_hook_job_started = var.runner_hook_job_started
253+
runner_hook_job_completed = var.runner_hook_job_completed
252254
key_name = var.key_name
253255
runner_ec2_tags = var.runner_ec2_tags
254256

Diff for: modules/multi-runner/README.md

+1-1
Large diffs are not rendered by default.

Diff for: modules/multi-runner/runners.tf

+9-7
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,15 @@ module "runners" {
8686
role_path = var.role_path
8787
role_permissions_boundary = var.role_permissions_boundary
8888

89-
enable_userdata = each.value.runner_config.enable_userdata
90-
userdata_template = each.value.runner_config.userdata_template
91-
userdata_content = each.value.runner_config.userdata_content
92-
userdata_pre_install = each.value.runner_config.userdata_pre_install
93-
userdata_post_install = each.value.runner_config.userdata_post_install
94-
key_name = var.key_name
95-
runner_ec2_tags = each.value.runner_config.runner_ec2_tags
89+
enable_userdata = each.value.runner_config.enable_userdata
90+
userdata_template = each.value.runner_config.userdata_template
91+
userdata_content = each.value.runner_config.userdata_content
92+
userdata_pre_install = each.value.runner_config.userdata_pre_install
93+
userdata_post_install = each.value.runner_config.userdata_post_install
94+
runner_hook_job_started = each.value.runner_config.runner_hook_job_started
95+
runner_hook_job_completed = each.value.runner_config.runner_hook_job_completed
96+
key_name = var.key_name
97+
runner_ec2_tags = each.value.runner_config.runner_ec2_tags
9698

9799
create_service_linked_role_spot = each.value.runner_config.create_service_linked_role_spot
98100

Diff for: modules/multi-runner/variables.tf

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ variable "multi_runner_config" {
7878
cloudwatch_config = optional(string, null)
7979
userdata_pre_install = optional(string, "")
8080
userdata_post_install = optional(string, "")
81+
runner_hook_job_started = optional(string, "")
82+
runner_hook_job_completed = optional(string, "")
8183
runner_ec2_tags = optional(map(string), {})
8284
runner_iam_role_managed_policy_arns = optional(list(string), [])
8385
vpc_id = optional(string, null)
@@ -180,6 +182,8 @@ variable "multi_runner_config" {
180182
cloudwatch_config: "(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."
181183
userdata_pre_install: "Script to be ran before the GitHub Actions runner is installed on the EC2 instances"
182184
userdata_post_install: "Script to be ran after the GitHub Actions runner is installed on the EC2 instances"
185+
runner_hook_job_started: "Script to be ran in the runner environment at the beginning of every job"
186+
runner_hook_job_completed: "Script to be ran in the runner environment at the end of every job"
183187
runner_ec2_tags: "Map of tags that will be added to the launch template instance tag specifications."
184188
runner_iam_role_managed_policy_arns: "Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role"
185189
vpc_id: "The VPC for security groups of the action runners. If not set uses the value of `var.vpc_id`."

Diff for: modules/runners/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ yarn run dist
203203
| <a name="input_runner_disable_default_labels"></a> [runner\_disable\_default\_labels](#input\_runner\_disable\_default\_labels) | Disable default labels for the runners (os, architecture and `self-hosted`). If enabled, the runner will only have the extra labels provided in `runner_extra_labels`. | `bool` | `false` | no |
204204
| <a name="input_runner_ec2_tags"></a> [runner\_ec2\_tags](#input\_runner\_ec2\_tags) | Map of tags that will be added to the launch template instance tag specifications. | `map(string)` | `{}` | no |
205205
| <a name="input_runner_group_name"></a> [runner\_group\_name](#input\_runner\_group\_name) | Name of the runner group. | `string` | `"Default"` | no |
206+
| <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 |
207+
| <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 |
206208
| <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 |
207209
| <a name="input_runner_labels"></a> [runner\_labels](#input\_runner\_labels) | All the labels for the runners (GitHub) including the default one's(e.g: self-hosted, linux, x64, label1, label2). Separate each label by a comma | `list(string)` | n/a | yes |
208210
| <a name="input_runner_log_files"></a> [runner\_log\_files](#input\_runner\_log\_files) | (optional) List of logfiles to send to CloudWatch, will only be used if `enable_cloudwatch_agent` is set to true. Object description: `log_group_name`: Name of the log group, `prefix_log_group`: If true, the log group name will be prefixed with `/github-self-hosted-runners/<var.prefix>`, `file_path`: path to the log file, `log_stream_name`: name of the log stream. | <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 |

Diff for: modules/runners/main.tf

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ locals {
5454
S3_LOCATION_RUNNER_DISTRIBUTION = local.s3_location_runner_distribution
5555
RUNNER_ARCHITECTURE = var.runner_architecture
5656
})
57-
post_install = var.userdata_post_install
57+
post_install = var.userdata_post_install
58+
hook_job_started = var.runner_hook_job_started
59+
hook_job_completed = var.runner_hook_job_completed
5860
start_runner = templatefile(local.userdata_start_runner[var.runner_os], {
5961
metadata_tags = var.metadata_options != null ? var.metadata_options.instance_metadata_tags : "enabled"
6062
})

Diff for: modules/runners/templates/user-data.sh

+16
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,20 @@ ${install_runner}
6262

6363
${post_install}
6464

65+
# Register runner job hooks
66+
# Ref: https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md
67+
%{ if hook_job_started != "" }
68+
cat > /opt/actions-runner/hook_job_started.sh << EOF
69+
${hook_job_started}
70+
EOF
71+
echo ACTIONS_RUNNER_HOOK_JOB_STARTED=/opt/actions-runner/hook_job_started.sh | tee -a /opt/actions-runner/.env
72+
%{ endif }
73+
74+
%{ if hook_job_completed != "" }
75+
cat > /opt/actions-runner/hook_job_completed.sh << EOF
76+
${hook_job_completed}
77+
EOF
78+
echo ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/opt/actions-runner/hook_job_completed.sh | tee -a /opt/actions-runner/.env
79+
%{ endif }
80+
6581
${start_runner}

Diff for: modules/runners/variables.tf

+12
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ variable "userdata_post_install" {
172172
default = ""
173173
}
174174

175+
variable "runner_hook_job_started" {
176+
description = "Script to be ran in the runner environment at the beginning of every job"
177+
type = string
178+
default = ""
179+
}
180+
181+
variable "runner_hook_job_completed" {
182+
description = "Script to be ran in the runner environment at the end of every job"
183+
type = string
184+
default = ""
185+
}
186+
175187
variable "sqs_build_queue" {
176188
description = "SQS queue to consume accepted build events."
177189
type = object({

Diff for: variables.tf

+12
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,18 @@ variable "userdata_post_install" {
280280
description = "Script to be ran after the GitHub Actions runner is installed on the EC2 instances"
281281
}
282282

283+
variable "runner_hook_job_started" {
284+
type = string
285+
default = ""
286+
description = "Script to be ran in the runner environment at the beginning of every job"
287+
}
288+
289+
variable "runner_hook_job_completed" {
290+
type = string
291+
default = ""
292+
description = "Script to be ran in the runner environment at the end of every job"
293+
}
294+
283295
variable "idle_config" {
284296
description = "List of time periods, defined as a cron expression, to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle."
285297
type = list(object({

0 commit comments

Comments
 (0)