From 42f40ea51fbe3933800f02af5f1bf71671540ca5 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Thu, 30 Sep 2021 11:17:09 -0400 Subject: [PATCH 01/13] feat(log): Adding Support for JSON logging --- README.md | 2 ++ main.tf | 2 ++ modules/runner-binaries-syncer/README.md | 1 + .../runner-binaries-syncer/package.json | 5 ++-- .../runner-binaries-syncer/src/lambda.ts | 9 ++++++ .../src/syncer/modules.d.ts | 5 ++++ .../lambdas/runner-binaries-syncer/yarn.lock | 15 ++++++++++ .../runner-binaries-syncer.tf | 1 + modules/runner-binaries-syncer/variables.tf | 6 ++++ modules/runners/README.md | 2 ++ modules/runners/lambdas/runners/package.json | 3 +- modules/runners/lambdas/runners/src/lambda.ts | 27 ++++++++++++++---- .../runners/src/scale-runners/modules.d.ts | 9 +++--- modules/runners/lambdas/runners/yarn.lock | 15 ++++++++++ modules/runners/scale-down.tf | 7 +++-- modules/runners/scale-up.tf | 9 +++--- modules/runners/variables.tf | 6 ++++ modules/webhook/README.md | 3 +- modules/webhook/lambdas/webhook/package.json | 3 +- modules/webhook/lambdas/webhook/src/lambda.ts | 13 +++++++-- .../lambdas/webhook/src/webhook/handler.ts | 6 ++-- .../lambdas/webhook/src/webhook/modules.d.ts | 8 ++++++ modules/webhook/lambdas/webhook/yarn.lock | 15 ++++++++++ modules/webhook/variables.tf | 6 ++++ modules/webhook/webhook.tf | 1 + modules/webhook/yarn.lock | 28 +++++++++++++++++++ variables.tf | 14 ++++++++++ 27 files changed, 194 insertions(+), 27 deletions(-) create mode 100644 modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts create mode 100644 modules/webhook/lambdas/webhook/src/webhook/modules.d.ts create mode 100644 modules/webhook/yarn.lock diff --git a/README.md b/README.md index ead428f14d..f5151e05bf 100644 --- a/README.md +++ b/README.md @@ -386,6 +386,7 @@ No requirements. | lambda\_s3\_bucket | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | | lambda\_security\_group\_ids | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | | lambda\_subnet\_ids | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | | market\_options | Market options for the action runner instances. Setting the value to `null` let the scaler create on-demand instances instead of spot instances. | `string` | `"spot"` | no | | minimum\_running\_time\_in\_minutes | The time an ec2 action runner should be running at minimum before terminated if not busy. | `number` | `5` | no | @@ -398,6 +399,7 @@ No requirements. | runner\_binaries\_syncer\_lambda\_timeout | Time out of the binaries sync lambda in seconds. | `number` | `300` | no | | runner\_binaries\_syncer\_lambda\_zip | File location of the binaries sync lambda zip file. | `string` | `null` | no | | runner\_boot\_time\_in\_minutes | The minimum time for an EC2 runner to boot and register as a runner. | `number` | `5` | no | +| runner\_egress\_rules | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | | runner\_extra\_labels | Extra labels for the runners (GitHub). Separate each label by a comma | `string` | `""` | no | | runner\_group\_name | Name of the runner group. | `string` | `"Default"` | no | | runner\_iam\_role\_managed\_policy\_arns | Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role | `list(string)` | `[]` | no | diff --git a/main.tf b/main.tf index 36aa30fe20..3211c9a99d 100644 --- a/main.tf +++ b/main.tf @@ -131,6 +131,8 @@ module "runners" { ghes_url = var.ghes_url kms_key_arn = var.kms_key_arn + + log_type = var.log_type } module "runner_binaries" { diff --git a/modules/runner-binaries-syncer/README.md b/modules/runner-binaries-syncer/README.md index a167e567de..20c762824b 100644 --- a/modules/runner-binaries-syncer/README.md +++ b/modules/runner-binaries-syncer/README.md @@ -79,6 +79,7 @@ No Modules. | lambda\_subnet\_ids | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | | lambda\_timeout | Time out of the lambda in seconds. | `number` | `300` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | | role\_path | The path that will be added to the role, if not set the environment name will be used. | `string` | `null` | no | | role\_permissions\_boundary | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json index f9e2b97736..1397bc7385 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json @@ -33,6 +33,7 @@ "typescript": "^4.3.4" }, "dependencies": { - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.1", + "tslog": "^3.2.2" } -} \ No newline at end of file +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts index 85ea9622bd..67fc6569a0 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts @@ -1,7 +1,16 @@ import { handle } from './syncer/handler'; +import { Logger } from 'tslog'; // eslint-disable-next-line export const handler = async (event: any, context: any, callback: any): Promise => { + const logger = new Logger({ + name: 'runner-binaries-syncer', + requestId: context.awsRequestId, + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', + displayInstanceName: false, + }); + logger.debug(JSON.stringify(event)); try { await handle(); callback(null); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts new file mode 100644 index 0000000000..ab65068e07 --- /dev/null +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts @@ -0,0 +1,5 @@ +declare namespace NodeJS { + export interface ProcessEnv { + LOG_TYPE: 'json' | 'pretty' | 'hidden'; + } +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock index 2631bc24d5..ad8ca0c9f0 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock @@ -3885,6 +3885,14 @@ source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5. buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.19: + version "0.5.20" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" + integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -4200,6 +4208,13 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslog@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.2.2.tgz#5bbaa1fab685c4273e59b38064227321a69a0694" + integrity sha1-W7qh+raFxCc+WbOAZCJzIaaaBpQ= + dependencies: + source-map-support "^0.5.19" + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" diff --git a/modules/runner-binaries-syncer/runner-binaries-syncer.tf b/modules/runner-binaries-syncer/runner-binaries-syncer.tf index e57dfc0c4f..23dfd4cfce 100644 --- a/modules/runner-binaries-syncer/runner-binaries-syncer.tf +++ b/modules/runner-binaries-syncer/runner-binaries-syncer.tf @@ -22,6 +22,7 @@ resource "aws_lambda_function" "syncer" { S3_OBJECT_KEY = local.action_runner_distribution_object_key GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = var.runner_allow_prerelease_binaries + LOG_TYPE = var.log_type } } dynamic "vpc_config" { diff --git a/modules/runner-binaries-syncer/variables.tf b/modules/runner-binaries-syncer/variables.tf index d2daafec3f..8911b9fa44 100644 --- a/modules/runner-binaries-syncer/variables.tf +++ b/modules/runner-binaries-syncer/variables.tf @@ -93,3 +93,9 @@ variable "lambda_security_group_ids" { type = list(string) default = [] } + +variable "log_type" { + description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " + type = string + default = "pretty" +} diff --git a/modules/runners/README.md b/modules/runners/README.md index 280b5a1300..0c5ab0d292 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -93,6 +93,7 @@ No Modules. | block\_device\_mappings | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops` | `map(string)` | `{}` | no | | 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. | `string` | `null` | no | | create\_service\_linked\_role\_spot | (optional) create the service linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | +| egress\_rules | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | | enable\_cloudwatch\_agent | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no | | enable\_organization\_runners | n/a | `bool` | n/a | yes | | enable\_ssm\_on\_runners | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes | @@ -111,6 +112,7 @@ No Modules. | lambda\_timeout\_scale\_down | Time out for the scale down lambda in seconds. | `number` | `60` | no | | lambda\_timeout\_scale\_up | Time out for the scale up lambda in seconds. | `number` | `60` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | | market\_options | Market options for the action runner instances. | `string` | `"spot"` | no | | minimum\_running\_time\_in\_minutes | The time an ec2 action runner should be running at minimum before terminated if non busy. | `number` | `5` | no | diff --git a/modules/runners/lambdas/runners/package.json b/modules/runners/lambdas/runners/package.json index cd35e2d272..d30c9df118 100644 --- a/modules/runners/lambdas/runners/package.json +++ b/modules/runners/lambdas/runners/package.json @@ -43,6 +43,7 @@ "@types/node": "^16.6.1", "aws-sdk": "^2.970.0", "cron-parser": "^3.3.0", + "tslog": "^3.2.2", "typescript": "^4.2.3" } -} \ No newline at end of file +} diff --git a/modules/runners/lambdas/runners/src/lambda.ts b/modules/runners/lambdas/runners/src/lambda.ts index 848bda9c66..36ead1c6e1 100644 --- a/modules/runners/lambdas/runners/src/lambda.ts +++ b/modules/runners/lambdas/runners/src/lambda.ts @@ -1,9 +1,18 @@ import { scaleUp as scaleUpAction } from './scale-runners/scale-up'; import { scaleDown as scaleDownAction } from './scale-runners/scale-down'; -import { SQSEvent, ScheduledEvent, Context } from 'aws-lambda'; +import { SQSEvent, ScheduledEvent, Context, Callback } from 'aws-lambda'; +import { Logger } from 'tslog'; +import 'source-map-support/register'; -export const scaleUp = async (event: SQSEvent, context: Context, callback: any): Promise => { - console.debug(JSON.stringify(event)); +export const scaleUp = async (event: SQSEvent, context: Context, callback: Callback): Promise => { + const logger = new Logger({ + name: 'scale-up', + requestId: context.awsRequestId, + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', + displayInstanceName: false, + }); + logger.debug(JSON.stringify(event)); try { for (const e of event.Records) { await scaleUpAction(e.eventSource, JSON.parse(e.body)); @@ -11,17 +20,23 @@ export const scaleUp = async (event: SQSEvent, context: Context, callback: any): callback(null); } catch (e) { - console.error(e); + logger.error(e); callback('Failed handling SQS event'); } }; -export const scaleDown = async (event: ScheduledEvent, context: Context, callback: any): Promise => { +export const scaleDown = async (event: ScheduledEvent, context: Context, callback: Callback): Promise => { + const logger = new Logger({ + name: 'scale-down', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', + displayInstanceName: false, + }); try { await scaleDownAction(); callback(null); } catch (e) { - console.error(e); + logger.error(e); callback('Failed'); } }; diff --git a/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts b/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts index 0710eb74a5..3a5397c980 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts @@ -1,15 +1,16 @@ declare namespace NodeJS { export interface ProcessEnv { + AWS_REGION: string; ENVIRONMENT: string; - SUBNET_IDS: string; GHES_URL: string; - SCALE_DOWN_CONFIG: string; - MINIMUM_RUNNING_TIME_IN_MINUTES: string; LAUNCH_TEMPLATE_NAME: string; - AWS_REGION: string; + LOG_TYPE: 'json' | 'pretty' | 'hidden'; + MINIMUM_RUNNING_TIME_IN_MINUTES: string; PARAMETER_GITHUB_APP_CLIENT_ID_NAME: string; PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME: string; PARAMETER_GITHUB_APP_ID_NAME: string; PARAMETER_GITHUB_APP_KEY_BASE64_NAME: string; + SCALE_DOWN_CONFIG: string; + SUBNET_IDS: string; } } diff --git a/modules/runners/lambdas/runners/yarn.lock b/modules/runners/lambdas/runners/yarn.lock index df1d010e97..bfb586c4bc 100644 --- a/modules/runners/lambdas/runners/yarn.lock +++ b/modules/runners/lambdas/runners/yarn.lock @@ -4001,6 +4001,14 @@ source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5. buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.19: + version "0.5.20" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" + integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -4273,6 +4281,13 @@ tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tslog@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.2.2.tgz#5bbaa1fab685c4273e59b38064227321a69a0694" + integrity sha1-W7qh+raFxCc+WbOAZCJzIaaaBpQ= + dependencies: + source-map-support "^0.5.19" + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" diff --git a/modules/runners/scale-down.tf b/modules/runners/scale-down.tf index 431cdc8ddb..4c82c1755a 100644 --- a/modules/runners/scale-down.tf +++ b/modules/runners/scale-down.tf @@ -14,14 +14,15 @@ resource "aws_lambda_function" "scale_down" { environment { variables = { ENVIRONMENT = var.environment - MINIMUM_RUNNING_TIME_IN_MINUTES = var.minimum_running_time_in_minutes - RUNNER_BOOT_TIME_IN_MINUTES = var.runner_boot_time_in_minutes - SCALE_DOWN_CONFIG = jsonencode(var.idle_config) GHES_URL = var.ghes_url + LOG_TYPE = var.log_type + MINIMUM_RUNNING_TIME_IN_MINUTES = var.minimum_running_time_in_minutes PARAMETER_GITHUB_APP_CLIENT_ID_NAME = var.github_app_parameters.client_id.name PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME = var.github_app_parameters.client_secret.name PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name + RUNNER_BOOT_TIME_IN_MINUTES = var.runner_boot_time_in_minutes + SCALE_DOWN_CONFIG = jsonencode(var.idle_config) } } diff --git a/modules/runners/scale-up.tf b/modules/runners/scale-up.tf index d7b4f6b080..b9b7ca7a45 100644 --- a/modules/runners/scale-up.tf +++ b/modules/runners/scale-up.tf @@ -17,15 +17,16 @@ resource "aws_lambda_function" "scale_up" { ENABLE_ORGANIZATION_RUNNERS = var.enable_organization_runners ENVIRONMENT = var.environment GHES_URL = var.ghes_url - RUNNER_EXTRA_LABELS = var.runner_extra_labels - RUNNER_GROUP_NAME = var.runner_group_name - RUNNERS_MAXIMUM_COUNT = var.runners_maximum_count LAUNCH_TEMPLATE_NAME = join(",", [for template in aws_launch_template.runner : template.name]) - SUBNET_IDS = join(",", var.subnet_ids) + LOG_TYPE = var.log_type PARAMETER_GITHUB_APP_CLIENT_ID_NAME = var.github_app_parameters.client_id.name PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME = var.github_app_parameters.client_secret.name PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name + RUNNER_EXTRA_LABELS = var.runner_extra_labels + RUNNER_GROUP_NAME = var.runner_group_name + RUNNERS_MAXIMUM_COUNT = var.runners_maximum_count + SUBNET_IDS = join(",", var.subnet_ids) } } diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index bc3f6be0c0..3e84c3588d 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -364,3 +364,9 @@ variable "egress_rules" { description = null }] } + +variable "log_type" { + description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " + type = string + default = "pretty" +} diff --git a/modules/webhook/README.md b/modules/webhook/README.md index 86d029bbb9..ee177f805a 100644 --- a/modules/webhook/README.md +++ b/modules/webhook/README.md @@ -74,9 +74,10 @@ No Modules. | lambda\_s3\_bucket | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | | lambda\_timeout | Time out of the lambda in seconds. | `number` | `10` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | | repository\_white\_list | List of repositories allowed to use the github app | `list(string)` | `[]` | no | -| role\_path | The path that will be added to the role, if not set the environment name will be used. | `string` | `null` | no | +| role\_path | The path that will be added to the role; if not set, the environment name will be used. | `string` | `null` | no | | role\_permissions\_boundary | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | | runner\_extra\_labels | Extra labels for the runners (GitHub). Separate each label by a comma | `string` | `""` | no | | sqs\_build\_queue | SQS queue to publish accepted build events. |
object({
id = string
arn = string
})
| n/a | yes | diff --git a/modules/webhook/lambdas/webhook/package.json b/modules/webhook/lambdas/webhook/package.json index cc08dd1a1c..d22c43dd50 100644 --- a/modules/webhook/lambdas/webhook/package.json +++ b/modules/webhook/lambdas/webhook/package.json @@ -40,6 +40,7 @@ "@aws-sdk/client-ssm": "^3.26.0", "@octokit/rest": "^18.9.1", "@octokit/webhooks": "^9.12.0", - "aws-lambda": "^1.0.6" + "aws-lambda": "^1.0.6", + "tslog": "^3.2.2" } } diff --git a/modules/webhook/lambdas/webhook/src/lambda.ts b/modules/webhook/lambdas/webhook/src/lambda.ts index 29a96dd0bd..2614ea4974 100644 --- a/modules/webhook/lambdas/webhook/src/lambda.ts +++ b/modules/webhook/lambdas/webhook/src/lambda.ts @@ -1,8 +1,17 @@ import { handle } from './webhook/handler'; -import { APIGatewayEvent, Context } from 'aws-lambda'; +import { APIGatewayEvent, Context, Callback } from 'aws-lambda'; +import { Logger } from 'tslog'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const githubWebhook = async (event: APIGatewayEvent, context: Context, callback: any): Promise => { +export const githubWebhook = async (event: APIGatewayEvent, context: Context, callback: Callback): Promise => { + const logger = new Logger({ + name: 'webhook', + requestId: context.awsRequestId, + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', + displayInstanceName: false, + }); + logger.debug(JSON.stringify(event)); try { const statusCode = await handle(event.headers, event.body); callback(null, { diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.ts index 1b2c4d5d08..527268343d 100644 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.ts +++ b/modules/webhook/lambdas/webhook/src/webhook/handler.ts @@ -39,7 +39,7 @@ export const handle = async (headers: IncomingHttpHeaders, payload: any): Promis return 500; } - const secret = await getParameterValue(process.env.ENVIRONMENT as string, 'github_app_webhook_secret'); + const secret = await getParameterValue(process.env.ENVIRONMENT, 'github_app_webhook_secret'); const webhooks = new Webhooks({ secret: secret, @@ -115,14 +115,14 @@ async function handleCheckRun(body: CheckRunEvent, githubEvent: string): Promise } function isRepoNotAllowed(body: WorkflowJob | CheckRunEvent): boolean { - const repositoryWhiteListEnv = (process.env.REPOSITORY_WHITE_LIST as string) || '[]'; + const repositoryWhiteListEnv = process.env.REPOSITORY_WHITE_LIST || '[]'; const repositoryWhiteList = JSON.parse(repositoryWhiteListEnv) as Array; return repositoryWhiteList.length > 0 && !repositoryWhiteList.includes(body.repository.full_name); } function isRunnerNotAllowed(job: WorkflowJob): boolean { - const runnerLabelsEnv = (process.env.RUNNER_LABELS as string) || '[]'; + const runnerLabelsEnv = process.env.RUNNER_LABELS || '[]'; const runnerLabels = new Set(JSON.parse(runnerLabelsEnv) as Array); // ensure the self-hosted label is in the list. diff --git a/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts b/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts new file mode 100644 index 0000000000..2cbb2475d2 --- /dev/null +++ b/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts @@ -0,0 +1,8 @@ +declare namespace NodeJS { + export interface ProcessEnv { + ENVIRONMENT: string; + LOG_TYPE: 'json' | 'pretty' | 'hidden'; + REPOSITORY_WHITE_LIST: string; + RUNNER_LABELS: string; + } +} diff --git a/modules/webhook/lambdas/webhook/yarn.lock b/modules/webhook/lambdas/webhook/yarn.lock index f2789f88d8..a35e33a25c 100644 --- a/modules/webhook/lambdas/webhook/yarn.lock +++ b/modules/webhook/lambdas/webhook/yarn.lock @@ -4875,6 +4875,14 @@ source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5. buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.19: + version "0.5.20" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" + integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -5205,6 +5213,13 @@ tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tslog@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.2.2.tgz#5bbaa1fab685c4273e59b38064227321a69a0694" + integrity sha1-W7qh+raFxCc+WbOAZCJzIaaaBpQ= + dependencies: + source-map-support "^0.5.19" + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" diff --git a/modules/webhook/variables.tf b/modules/webhook/variables.tf index d9187f9aa4..c2b97be118 100644 --- a/modules/webhook/variables.tf +++ b/modules/webhook/variables.tf @@ -88,3 +88,9 @@ variable "runner_extra_labels" { type = string default = "" } + +variable "log_type" { + description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " + type = string + default = "pretty" +} diff --git a/modules/webhook/webhook.tf b/modules/webhook/webhook.tf index 5e7b8373cf..3bc9fba598 100644 --- a/modules/webhook/webhook.tf +++ b/modules/webhook/webhook.tf @@ -13,6 +13,7 @@ resource "aws_lambda_function" "webhook" { environment { variables = { ENVIRONMENT = var.environment + LOG_TYPE = var.log_type SQS_URL_WEBHOOK = var.sqs_build_queue.id REPOSITORY_WHITE_LIST = jsonencode(var.repository_white_list) RUNNER_LABELS = jsonencode(split(",", var.runner_extra_labels)) diff --git a/modules/webhook/yarn.lock b/modules/webhook/yarn.lock new file mode 100644 index 0000000000..7480029b41 --- /dev/null +++ b/modules/webhook/yarn.lock @@ -0,0 +1,28 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U= + +source-map-support@^0.5.19: + version "0.5.20" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" + integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= + +tslog@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.2.2.tgz#5bbaa1fab685c4273e59b38064227321a69a0694" + integrity sha1-W7qh+raFxCc+WbOAZCJzIaaaBpQ= + dependencies: + source-map-support "^0.5.19" diff --git a/variables.tf b/variables.tf index fca140b685..3d2a1f565b 100644 --- a/variables.tf +++ b/variables.tf @@ -392,3 +392,17 @@ variable "runner_egress_rules" { description = null }] } + +variable "log_type" { + description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " + type = string + default = "pretty" + validation { + condition = anytrue([ + var.log_type == "json", + var.log_type == "pretty", + var.log_type == "hidden", + ]) + error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." + } +} From 2731c2386ed041dbdfef41575eea5f4c5d4456fd Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 1 Oct 2021 08:39:08 -0400 Subject: [PATCH 02/13] Passing in log_type to other lambdas --- main.tf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.tf b/main.tf index 3211c9a99d..109bd81c60 100644 --- a/main.tf +++ b/main.tf @@ -64,6 +64,8 @@ module "webhook" { role_path = var.role_path role_permissions_boundary = var.role_permissions_boundary repository_white_list = var.repository_white_list + + log_type = var.log_type } module "runners" { @@ -156,6 +158,8 @@ module "runner_binaries" { role_path = var.role_path role_permissions_boundary = var.role_permissions_boundary + + log_type = var.log_type } resource "aws_resourcegroups_group" "resourcegroups_group" { From 2add2af2be838deb54434d9d6d4deb9b3e675fb9 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Mon, 4 Oct 2021 10:13:59 -0400 Subject: [PATCH 03/13] Casting e as Error --- modules/webhook/lambdas/webhook/src/lambda.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/webhook/lambdas/webhook/src/lambda.ts b/modules/webhook/lambdas/webhook/src/lambda.ts index 2614ea4974..0d5f0acdfe 100644 --- a/modules/webhook/lambdas/webhook/src/lambda.ts +++ b/modules/webhook/lambdas/webhook/src/lambda.ts @@ -18,6 +18,6 @@ export const githubWebhook = async (event: APIGatewayEvent, context: Context, ca statusCode: statusCode, }); } catch (e) { - callback(e); + callback(e as Error); } }; From d6ea524c7aa275d1af2859179eab4ae66066aa21 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 8 Oct 2021 12:09:48 -0400 Subject: [PATCH 04/13] Add log_level variable, fix formatting --- README.md | 21 +++++++++++-- modules/runner-binaries-syncer/README.md | 1 + .../runner-binaries-syncer/src/lambda.ts | 19 +++++++----- .../src/syncer/modules.d.ts | 1 + .../runner-binaries-syncer.tf | 5 +-- modules/runner-binaries-syncer/variables.tf | 26 ++++++++++++++++ modules/runners/README.md | 28 ++++++++++++++++- modules/runners/lambdas/runners/src/lambda.ts | 31 +++++++++---------- .../runners/src/scale-runners/gh-auth.ts | 2 +- .../runners/src/scale-runners/modules.d.ts | 1 + modules/runners/scale-down.tf | 4 ++- modules/runners/scale-up.tf | 4 ++- modules/runners/variables.tf | 26 ++++++++++++++++ modules/webhook/README.md | 1 + modules/webhook/lambdas/webhook/src/lambda.ts | 20 ++++++------ .../lambdas/webhook/src/webhook/modules.d.ts | 1 + modules/webhook/variables.tf | 26 ++++++++++++++++ modules/webhook/webhook.tf | 3 +- variables.tf | 18 +++++++++++ 19 files changed, 196 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 06c6d4929e..8a38a7a86c 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,23 @@ No requirements. | aws | n/a | | random | n/a | +## Modules + +| Name | Source | Version | +|------|--------|---------| +| runner_binaries | ./modules/runner-binaries-syncer | | +| runners | ./modules/runners | | +| ssm | ./modules/ssm | | +| webhook | ./modules/webhook | | + +## Resources + +| Name | +|------| +| [aws_resourcegroups_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | +| [aws_sqs_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | +| [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | + ## Inputs | Name | Description | Type | Default | Required | @@ -358,8 +375,8 @@ No requirements. | enable\_organization\_runners | Register runners to organization, instead of repo level | `bool` | `false` | no | | enable\_ssm\_on\_runners | Enable to allow access the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | `false` | no | | environment | A name that identifies the environment, used as prefix and for tagging. | `string` | n/a | yes | +| ghes\_ssl\_verify | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | | ghes\_url | GitHub Enterprise Server URL. Example: https://github.internal.co - DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | -| ghes\_ssl\_verify | GitHub Enterprise SSL verification. Set to `false` when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | | github\_app | GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
client_id = string
client_secret = string
webhook_secret = string
})
| n/a | yes | | idle\_config | List of time period that can be defined as 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. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | | 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 | @@ -370,6 +387,7 @@ No requirements. | lambda\_s3\_bucket | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | | lambda\_security\_group\_ids | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | | lambda\_subnet\_ids | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| log\_level | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | | log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | | market\_options | Market options for the action runner instances. Setting the value to `null` let the scaler create on-demand instances instead of spot instances. | `string` | `"spot"` | no | @@ -417,7 +435,6 @@ No requirements. | runners | n/a | | ssm\_parameters | n/a | | webhook | n/a | - ## Contribution diff --git a/modules/runner-binaries-syncer/README.md b/modules/runner-binaries-syncer/README.md index 20c762824b..f83480e694 100644 --- a/modules/runner-binaries-syncer/README.md +++ b/modules/runner-binaries-syncer/README.md @@ -79,6 +79,7 @@ No Modules. | lambda\_subnet\_ids | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | | lambda\_timeout | Time out of the lambda in seconds. | `number` | `300` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_level | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | | log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | | role\_path | The path that will be added to the role, if not set the environment name will be used. | `string` | `null` | no | diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts index 67fc6569a0..e08f409825 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts @@ -1,16 +1,19 @@ import { handle } from './syncer/handler'; import { Logger } from 'tslog'; +const rootLogger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + minLevel: process.env.LOG_LEVEL || 'info', + name: 'runner-binaries-syncer', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); + // eslint-disable-next-line export const handler = async (event: any, context: any, callback: any): Promise => { - const logger = new Logger({ - name: 'runner-binaries-syncer', - requestId: context.awsRequestId, - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', - displayInstanceName: false, - }); - logger.debug(JSON.stringify(event)); + rootLogger.setSettings({ requestId: context.awsRequestId }); + rootLogger.debug(JSON.stringify(event)); try { await handle(); callback(null); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts index ab65068e07..cff03913cb 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts @@ -1,5 +1,6 @@ declare namespace NodeJS { export interface ProcessEnv { + LOG_LEVEL: 'silly' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; LOG_TYPE: 'json' | 'pretty' | 'hidden'; } } diff --git a/modules/runner-binaries-syncer/runner-binaries-syncer.tf b/modules/runner-binaries-syncer/runner-binaries-syncer.tf index 23dfd4cfce..d1c5215183 100644 --- a/modules/runner-binaries-syncer/runner-binaries-syncer.tf +++ b/modules/runner-binaries-syncer/runner-binaries-syncer.tf @@ -18,11 +18,12 @@ resource "aws_lambda_function" "syncer" { environment { variables = { - S3_BUCKET_NAME = aws_s3_bucket.action_dist.id - S3_OBJECT_KEY = local.action_runner_distribution_object_key GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture GITHUB_RUNNER_ALLOW_PRERELEASE_BINARIES = var.runner_allow_prerelease_binaries + LOG_LEVEL = var.log_level LOG_TYPE = var.log_type + S3_BUCKET_NAME = aws_s3_bucket.action_dist.id + S3_OBJECT_KEY = local.action_runner_distribution_object_key } } dynamic "vpc_config" { diff --git a/modules/runner-binaries-syncer/variables.tf b/modules/runner-binaries-syncer/variables.tf index 8911b9fa44..a326c024fc 100644 --- a/modules/runner-binaries-syncer/variables.tf +++ b/modules/runner-binaries-syncer/variables.tf @@ -98,4 +98,30 @@ variable "log_type" { description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " type = string default = "pretty" + validation { + condition = anytrue([ + var.log_type == "json", + var.log_type == "pretty", + var.log_type == "hidden", + ]) + error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." + } +} + +variable "log_level" { + description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + type = string + default = "info" + validation { + condition = anytrue([ + var.log_level == "silly", + var.log_level == "trace", + var.log_level == "debug", + var.log_level == "info", + var.log_level == "warn", + var.log_level == "error", + var.log_level == "fatal", + ]) + error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + } } diff --git a/modules/runners/README.md b/modules/runners/README.md index 9e12bf4892..1551b7cdea 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -58,6 +58,31 @@ No requirements. |------|---------| | aws | n/a | +## Modules + +No Modules. + +## Resources + +| Name | +|------| +| [aws_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | +| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | +| [aws_cloudwatch_event_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | +| [aws_cloudwatch_event_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | +| [aws_cloudwatch_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | +| [aws_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | +| [aws_iam_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | +| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | +| [aws_lambda_event_source_mapping](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_event_source_mapping) | +| [aws_lambda_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | +| [aws_lambda_permission](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | +| [aws_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | +| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | +| [aws_ssm_parameter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | + ## Inputs | Name | Description | Type | Default | Required | @@ -73,6 +98,7 @@ No requirements. | enable\_organization\_runners | n/a | `bool` | n/a | yes | | enable\_ssm\_on\_runners | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes | | environment | A name that identifies the environment, used as prefix and for tagging. | `string` | n/a | yes | +| ghes\_ssl\_verify | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | | ghes\_url | GitHub Enterprise Server URL. DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | | github\_app\_parameters | Parameter Store for GitHub App Parameters. |
object({
key_base64 = map(string)
id = map(string)
client_id = map(string)
client_secret = map(string)
})
| n/a | yes | | idle\_config | List of time period that can be defined as 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. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | @@ -87,6 +113,7 @@ No requirements. | lambda\_timeout\_scale\_down | Time out for the scale down lambda in seconds. | `number` | `60` | no | | lambda\_timeout\_scale\_up | Time out for the scale up lambda in seconds. | `number` | `60` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_level | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | | log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | | market\_options | Market options for the action runner instances. | `string` | `"spot"` | no | @@ -127,7 +154,6 @@ No requirements. | role\_runner | n/a | | role\_scale\_down | n/a | | role\_scale\_up | n/a | - ## Philips Forest diff --git a/modules/runners/lambdas/runners/src/lambda.ts b/modules/runners/lambdas/runners/src/lambda.ts index 36ead1c6e1..9a03f71670 100644 --- a/modules/runners/lambdas/runners/src/lambda.ts +++ b/modules/runners/lambdas/runners/src/lambda.ts @@ -4,15 +4,19 @@ import { SQSEvent, ScheduledEvent, Context, Callback } from 'aws-lambda'; import { Logger } from 'tslog'; import 'source-map-support/register'; +export const rootLogger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + maskAnyRegEx: ['--token [A-Z0-9]*'], + minLevel: process.env.LOG_LEVEL || 'info', + name: 'scale-up', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); + export const scaleUp = async (event: SQSEvent, context: Context, callback: Callback): Promise => { - const logger = new Logger({ - name: 'scale-up', - requestId: context.awsRequestId, - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', - displayInstanceName: false, - }); - logger.debug(JSON.stringify(event)); + rootLogger.setSettings({ requestId: context.awsRequestId }); + rootLogger.debug(JSON.stringify(event)); try { for (const e of event.Records) { await scaleUpAction(e.eventSource, JSON.parse(e.body)); @@ -20,23 +24,18 @@ export const scaleUp = async (event: SQSEvent, context: Context, callback: Callb callback(null); } catch (e) { - logger.error(e); + rootLogger.error(e); callback('Failed handling SQS event'); } }; export const scaleDown = async (event: ScheduledEvent, context: Context, callback: Callback): Promise => { - const logger = new Logger({ - name: 'scale-down', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', - displayInstanceName: false, - }); + rootLogger.setSettings({ requestId: context.awsRequestId }); try { await scaleDownAction(); callback(null); } catch (e) { - logger.error(e); + rootLogger.error(e); callback('Failed'); } }; diff --git a/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts b/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts index cda6e5d3ab..bae49c860b 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts @@ -54,7 +54,7 @@ async function createAuth(installationId: number | undefined, ghesApiUrl: string }; if (installationId) authOptions = { ...authOptions, installationId }; - console.debug(ghesApiUrl); + console.debug(`GHES API URL: ${ghesApiUrl}`); if (ghesApiUrl) { authOptions.request = request.defaults({ baseUrl: ghesApiUrl, diff --git a/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts b/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts index 3a5397c980..6b11e1a626 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/modules.d.ts @@ -4,6 +4,7 @@ declare namespace NodeJS { ENVIRONMENT: string; GHES_URL: string; LAUNCH_TEMPLATE_NAME: string; + LOG_LEVEL: 'silly' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; LOG_TYPE: 'json' | 'pretty' | 'hidden'; MINIMUM_RUNNING_TIME_IN_MINUTES: string; PARAMETER_GITHUB_APP_CLIENT_ID_NAME: string; diff --git a/modules/runners/scale-down.tf b/modules/runners/scale-down.tf index 5056a417a2..28ba106402 100644 --- a/modules/runners/scale-down.tf +++ b/modules/runners/scale-down.tf @@ -10,14 +10,16 @@ resource "aws_lambda_function" "scale_down" { runtime = "nodejs12.x" timeout = var.lambda_timeout_scale_down tags = local.tags + memory_size = 512 environment { variables = { ENVIRONMENT = var.environment GHES_URL = var.ghes_url + LOG_LEVEL = var.log_level LOG_TYPE = var.log_type MINIMUM_RUNNING_TIME_IN_MINUTES = var.minimum_running_time_in_minutes - NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && ! var.ghes_ssl_verify ? 0 : 1 + NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 PARAMETER_GITHUB_APP_CLIENT_ID_NAME = var.github_app_parameters.client_id.name PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME = var.github_app_parameters.client_secret.name PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name diff --git a/modules/runners/scale-up.tf b/modules/runners/scale-up.tf index eaf9f645cd..9bed628e8b 100644 --- a/modules/runners/scale-up.tf +++ b/modules/runners/scale-up.tf @@ -10,6 +10,7 @@ resource "aws_lambda_function" "scale_up" { runtime = "nodejs12.x" timeout = var.lambda_timeout_scale_up reserved_concurrent_executions = 1 + memory_size = 512 tags = local.tags environment { @@ -17,9 +18,10 @@ resource "aws_lambda_function" "scale_up" { ENABLE_ORGANIZATION_RUNNERS = var.enable_organization_runners ENVIRONMENT = var.environment GHES_URL = var.ghes_url - NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && ! var.ghes_ssl_verify ? 0 : 1 LAUNCH_TEMPLATE_NAME = join(",", [for template in aws_launch_template.runner : template.name]) + LOG_LEVEL = var.log_level LOG_TYPE = var.log_type + NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 PARAMETER_GITHUB_APP_CLIENT_ID_NAME = var.github_app_parameters.client_id.name PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME = var.github_app_parameters.client_secret.name PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index 9a09b2e75e..bce303224a 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -375,4 +375,30 @@ variable "log_type" { description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " type = string default = "pretty" + validation { + condition = anytrue([ + var.log_type == "json", + var.log_type == "pretty", + var.log_type == "hidden", + ]) + error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." + } +} + +variable "log_level" { + description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + type = string + default = "info" + validation { + condition = anytrue([ + var.log_level == "silly", + var.log_level == "trace", + var.log_level == "debug", + var.log_level == "info", + var.log_level == "warn", + var.log_level == "error", + var.log_level == "fatal", + ]) + error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + } } diff --git a/modules/webhook/README.md b/modules/webhook/README.md index ee177f805a..48b7863296 100644 --- a/modules/webhook/README.md +++ b/modules/webhook/README.md @@ -74,6 +74,7 @@ No Modules. | lambda\_s3\_bucket | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | | lambda\_timeout | Time out of the lambda in seconds. | `number` | `10` | no | | lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | +| log\_level | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | | log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | | repository\_white\_list | List of repositories allowed to use the github app | `list(string)` | `[]` | no | diff --git a/modules/webhook/lambdas/webhook/src/lambda.ts b/modules/webhook/lambdas/webhook/src/lambda.ts index 0d5f0acdfe..af0f980df7 100644 --- a/modules/webhook/lambdas/webhook/src/lambda.ts +++ b/modules/webhook/lambdas/webhook/src/lambda.ts @@ -2,16 +2,18 @@ import { handle } from './webhook/handler'; import { APIGatewayEvent, Context, Callback } from 'aws-lambda'; import { Logger } from 'tslog'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const rootLogger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + minLevel: process.env.LOG_LEVEL || 'info', + name: 'webhook', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); + export const githubWebhook = async (event: APIGatewayEvent, context: Context, callback: Callback): Promise => { - const logger = new Logger({ - name: 'webhook', - requestId: context.awsRequestId, - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', - displayInstanceName: false, - }); - logger.debug(JSON.stringify(event)); + rootLogger.setSettings({ requestId: context.awsRequestId }); + rootLogger.debug(JSON.stringify(event)); try { const statusCode = await handle(event.headers, event.body); callback(null, { diff --git a/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts b/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts index 2cbb2475d2..d6972fd986 100644 --- a/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts +++ b/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts @@ -1,6 +1,7 @@ declare namespace NodeJS { export interface ProcessEnv { ENVIRONMENT: string; + LOG_LEVEL: 'silly' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; LOG_TYPE: 'json' | 'pretty' | 'hidden'; REPOSITORY_WHITE_LIST: string; RUNNER_LABELS: string; diff --git a/modules/webhook/variables.tf b/modules/webhook/variables.tf index c2b97be118..1960da2868 100644 --- a/modules/webhook/variables.tf +++ b/modules/webhook/variables.tf @@ -93,4 +93,30 @@ variable "log_type" { description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " type = string default = "pretty" + validation { + condition = anytrue([ + var.log_type == "json", + var.log_type == "pretty", + var.log_type == "hidden", + ]) + error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." + } +} + +variable "log_level" { + description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + type = string + default = "info" + validation { + condition = anytrue([ + var.log_level == "silly", + var.log_level == "trace", + var.log_level == "debug", + var.log_level == "info", + var.log_level == "warn", + var.log_level == "error", + var.log_level == "fatal", + ]) + error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + } } diff --git a/modules/webhook/webhook.tf b/modules/webhook/webhook.tf index 3bc9fba598..12819c2f68 100644 --- a/modules/webhook/webhook.tf +++ b/modules/webhook/webhook.tf @@ -13,10 +13,11 @@ resource "aws_lambda_function" "webhook" { environment { variables = { ENVIRONMENT = var.environment + LOG_LEVEL = var.log_level LOG_TYPE = var.log_type - SQS_URL_WEBHOOK = var.sqs_build_queue.id REPOSITORY_WHITE_LIST = jsonencode(var.repository_white_list) RUNNER_LABELS = jsonencode(split(",", var.runner_extra_labels)) + SQS_URL_WEBHOOK = var.sqs_build_queue.id } } diff --git a/variables.tf b/variables.tf index 5da6d088e0..98de63cd6b 100644 --- a/variables.tf +++ b/variables.tf @@ -412,3 +412,21 @@ variable "log_type" { error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." } } + +variable "log_level" { + description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + type = string + default = "info" + validation { + condition = anytrue([ + var.log_level == "silly", + var.log_level == "trace", + var.log_level == "debug", + var.log_level == "info", + var.log_level == "warn", + var.log_level == "error", + var.log_level == "fatal", + ]) + error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + } +} From c0ecddc38d396022fff88b58a171666daefdf109 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 8 Oct 2021 12:19:41 -0400 Subject: [PATCH 05/13] Correcting failed resolution --- .../lambdas/runner-binaries-syncer/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json index 819edb2335..0eb9b9a749 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "node-fetch": "^2.6.1", - "tslog": "^3.2.2" + "tslog": "^3.2.2", "axios": "^0.22.0" } -} \ No newline at end of file +} From a1aea0bcf2446c0d81f7f4f195f54086ae2b3a6b Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Mon, 11 Oct 2021 16:18:44 -0400 Subject: [PATCH 06/13] Using latest releases for testing --- .github/workflows/terraform.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index 194019e5f5..bc09017d72 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -13,12 +13,11 @@ env: tf_working_dir: "." AWS_REGION: eu-west-1 jobs: - verify_module: name: Verify module strategy: matrix: - terraform: [1.0.8] + terraform: [1.0.8] runs-on: ubuntu-latest container: image: hashicorp/terraform:${{ matrix.terraform }} @@ -43,7 +42,7 @@ jobs: strategy: fail-fast: false matrix: - terraform: [0.14.1, 0.15.0, 1.0.8] + terraform: [0.14.11, 0.15.5, 1.0.8] example: ["default", "ubuntu"] defaults: run: @@ -51,7 +50,7 @@ jobs: runs-on: ubuntu-latest container: image: hashicorp/terraform:${{ matrix.terraform }} - steps: + steps: - uses: actions/checkout@v2 - name: terraform init run: terraform init -get -backend=false -input=false @@ -61,5 +60,3 @@ jobs: continue-on-error: true - name: validate terraform run: terraform validate - - From 58e4a100af0d977d5f6fd0d5b1de573f62f49bd6 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Tue, 12 Oct 2021 10:29:05 -0400 Subject: [PATCH 07/13] Passing in log_level to sub-modules --- main.tf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main.tf b/main.tf index 243a7ff612..90c0892663 100644 --- a/main.tf +++ b/main.tf @@ -64,7 +64,8 @@ module "webhook" { role_permissions_boundary = var.role_permissions_boundary repository_white_list = var.repository_white_list - log_type = var.log_type + log_type = var.log_type + log_level = var.log_level } module "runners" { @@ -134,7 +135,8 @@ module "runners" { kms_key_arn = var.kms_key_arn - log_type = var.log_type + log_type = var.log_type + log_level = var.log_level } module "runner_binaries" { @@ -159,7 +161,8 @@ module "runner_binaries" { role_path = var.role_path role_permissions_boundary = var.role_permissions_boundary - log_type = var.log_type + log_type = var.log_type + log_level = var.log_level } resource "aws_resourcegroups_group" "resourcegroups_group" { From a930ff9e7b804895e2bc024a85cd5e5dc6cb2fd1 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Wed, 13 Oct 2021 14:45:12 -0400 Subject: [PATCH 08/13] Update terraform.yml --- .github/workflows/terraform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index bc09017d72..450976e2e1 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -42,7 +42,7 @@ jobs: strategy: fail-fast: false matrix: - terraform: [0.14.11, 0.15.5, 1.0.8] + terraform: [0.14.3, 0.15.5, 1.0.8] example: ["default", "ubuntu"] defaults: run: From f1d198a97e36c38390f055b73cdacf412fe117bf Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 15 Oct 2021 11:52:48 -0400 Subject: [PATCH 09/13] Manually removing `node-fetch` --- .../lambdas/runner-binaries-syncer/package.json | 1 - .../lambdas/runner-binaries-syncer/yarn.lock | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json index 74b82e2207..553a20481b 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json @@ -32,7 +32,6 @@ "typescript": "^4.3.4" }, "dependencies": { - "node-fetch": "^2.6.1", "tslog": "^3.2.2", "axios": "^0.22.0" } diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock index eef55919c6..8acd447b51 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock @@ -3153,7 +3153,7 @@ source-map-support@^0.5.12, source-map-support@^0.5.17: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.19: +source-map-support@^0.5.19, source-map-support@^0.5.6: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= @@ -3161,11 +3161,6 @@ source-map-support@^0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" From 36dda0b0a3d8e7bb3cd8df60961a41805c76172d Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 22 Oct 2021 08:38:48 -0400 Subject: [PATCH 10/13] Moving logger object to new file --- .../runner-binaries-syncer/src/lambda.ts | 15 ++------ .../src/syncer/handler.ts | 15 +++++--- .../src/syncer/logger.ts | 10 +++++ .../runner-binaries-syncer/tsconfig.json | 14 +++++-- modules/runners/lambdas/runners/src/lambda.ts | 38 +++++++------------ .../runners/src/scale-runners/gh-auth.ts | 5 ++- .../runners/src/scale-runners/logger.ts | 11 ++++++ .../runners/src/scale-runners/runners.ts | 9 +++-- .../runners/src/scale-runners/scale-down.ts | 37 +++++++++--------- .../runners/src/scale-runners/scale-up.ts | 19 ++++++---- modules/runners/lambdas/runners/tsconfig.json | 5 ++- modules/webhook/lambdas/webhook/src/lambda.ts | 15 ++------ .../webhook/src/webhook/handler.test.ts | 1 + .../lambdas/webhook/src/webhook/handler.ts | 23 ++++++----- .../lambdas/webhook/src/webhook/logger.ts | 10 +++++ modules/webhook/lambdas/webhook/tsconfig.json | 14 +++++-- modules/webhook/lambdas/webhook/yarn.lock | 7 +--- 17 files changed, 139 insertions(+), 109 deletions(-) create mode 100644 modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts create mode 100644 modules/runners/lambdas/runners/src/scale-runners/logger.ts create mode 100644 modules/webhook/lambdas/webhook/src/webhook/logger.ts diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts index e08f409825..b835538009 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts @@ -1,19 +1,10 @@ import { handle } from './syncer/handler'; -import { Logger } from 'tslog'; - -const rootLogger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - minLevel: process.env.LOG_LEVEL || 'info', - name: 'runner-binaries-syncer', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', -}); +import { logger } from './syncer/logger'; // eslint-disable-next-line export const handler = async (event: any, context: any, callback: any): Promise => { - rootLogger.setSettings({ requestId: context.awsRequestId }); - rootLogger.debug(JSON.stringify(event)); + logger.setSettings({ requestId: context.awsRequestId }); + logger.debug(JSON.stringify(event)); try { await handle(); callback(null); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/handler.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/handler.ts index 223e51c71d..c330ed5e03 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/handler.ts +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/handler.ts @@ -3,6 +3,9 @@ import { PassThrough } from 'stream'; import { S3 } from 'aws-sdk'; import AWS from 'aws-sdk'; import axios from 'axios'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); const versionKey = 'name'; @@ -22,7 +25,7 @@ async function getCachedVersion(s3: S3, cacheObject: CacheObject): Promise t.Key === versionKey); return versions.length === 1 ? versions[0].Value : undefined; } catch (e) { - console.debug('No tags found'); + logger.debug('No tags found'); return undefined; } } @@ -73,7 +76,7 @@ async function uploadToS3(s3: S3, cacheObject: CacheObject, actionRunnerReleaseA }) .promise(); - console.debug('Start downloading %s and uploading to S3.', actionRunnerReleaseAsset.name); + logger.debug('Start downloading %s and uploading to S3.', actionRunnerReleaseAsset.name); const readPromise = new Promise((resolve, reject) => { axios @@ -93,9 +96,9 @@ async function uploadToS3(s3: S3, cacheObject: CacheObject, actionRunnerReleaseA }); await Promise.all([readPromise, writePromise]) - .then(() => console.info(`The new distribution is uploaded to S3.`)) + .then(() => logger.info(`The new distribution is uploaded to S3.`)) .catch((error) => { - console.error(`Uploading of the new distribution to S3 failed: ${error}`); + logger.error(`Uploading of the new distribution to S3 failed: ${error}`); throw error; }); } @@ -120,10 +123,10 @@ export const handle = async (): Promise => { } const currentVersion = await getCachedVersion(s3, cacheObject); - console.debug('latest: ' + currentVersion); + logger.debug('latest: ' + currentVersion); if (currentVersion === undefined || currentVersion != actionRunnerReleaseAsset.name) { uploadToS3(s3, cacheObject, actionRunnerReleaseAsset); } else { - console.debug('Distribution is up-to-date, no action.'); + logger.debug('Distribution is up-to-date, no action.'); } }; diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts new file mode 100644 index 0000000000..ebae043deb --- /dev/null +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts @@ -0,0 +1,10 @@ +import { Logger } from 'tslog'; + +export const logger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + minLevel: process.env.LOG_LEVEL || 'info', + name: 'runner-binaries-syncer', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json index 64a2b54f25..764f2f6ae0 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json +++ b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json @@ -1,10 +1,13 @@ { "compilerOptions": { /* Basic Options */ - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "outDir": "build", - "lib": ["es2020", "DOM"] /* Specify library files to be included in the compilation. */, + "lib": [ + "es2020", + "DOM" + ] /* Specify library files to be included in the compilation. */, "allowJs": true /* Allow javascript files to be compiled. */, // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ @@ -54,7 +57,10 @@ /* Experimental Options */ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true + "resolveJsonModule": true, + "sourceMap": true }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/modules/runners/lambdas/runners/src/lambda.ts b/modules/runners/lambdas/runners/src/lambda.ts index 9a03f71670..a784c0d059 100644 --- a/modules/runners/lambdas/runners/src/lambda.ts +++ b/modules/runners/lambdas/runners/src/lambda.ts @@ -1,41 +1,31 @@ -import { scaleUp as scaleUpAction } from './scale-runners/scale-up'; -import { scaleDown as scaleDownAction } from './scale-runners/scale-down'; +import { scaleUp } from './scale-runners/scale-up'; +import { scaleDown } from './scale-runners/scale-down'; import { SQSEvent, ScheduledEvent, Context, Callback } from 'aws-lambda'; -import { Logger } from 'tslog'; +import { logger } from './scale-runners/logger'; import 'source-map-support/register'; -export const rootLogger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - maskAnyRegEx: ['--token [A-Z0-9]*'], - minLevel: process.env.LOG_LEVEL || 'info', - name: 'scale-up', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', -}); - -export const scaleUp = async (event: SQSEvent, context: Context, callback: Callback): Promise => { - rootLogger.setSettings({ requestId: context.awsRequestId }); - rootLogger.debug(JSON.stringify(event)); +export async function scaleUpHandler(event: SQSEvent, context: Context, callback: Callback): Promise { + logger.setSettings({ requestId: context.awsRequestId }); + logger.debug(JSON.stringify(event)); try { for (const e of event.Records) { - await scaleUpAction(e.eventSource, JSON.parse(e.body)); + await scaleUp(e.eventSource, JSON.parse(e.body)); } callback(null); } catch (e) { - rootLogger.error(e); + logger.error(e); callback('Failed handling SQS event'); } -}; +} -export const scaleDown = async (event: ScheduledEvent, context: Context, callback: Callback): Promise => { - rootLogger.setSettings({ requestId: context.awsRequestId }); +export async function scaleDownHandler(event: ScheduledEvent, context: Context, callback: Callback): Promise { + logger.setSettings({ requestId: context.awsRequestId }); try { - await scaleDownAction(); + await scaleDown(); callback(null); } catch (e) { - rootLogger.error(e); + logger.error(e); callback('Failed'); } -}; +} diff --git a/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts b/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts index 35ab3d3b28..d60d4bebc1 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/gh-auth.ts @@ -11,6 +11,9 @@ import { } from '@octokit/auth-app/dist-types/types'; import { OctokitOptions } from '@octokit/core/dist-types/types'; import { getParameterValue } from './ssm'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); export async function createOctoClient(token: string, ghesApiUrl = ''): Promise { const ocktokitOptions: OctokitOptions = { @@ -52,7 +55,7 @@ async function createAuth(installationId: number | undefined, ghesApiUrl: string }; if (installationId) authOptions = { ...authOptions, installationId }; - console.debug(`GHES API URL: ${ghesApiUrl}`); + logger.debug(`GHES API URL: ${ghesApiUrl}`); if (ghesApiUrl) { authOptions.request = request.defaults({ baseUrl: ghesApiUrl, diff --git a/modules/runners/lambdas/runners/src/scale-runners/logger.ts b/modules/runners/lambdas/runners/src/scale-runners/logger.ts new file mode 100644 index 0000000000..fcf2fda8b1 --- /dev/null +++ b/modules/runners/lambdas/runners/src/scale-runners/logger.ts @@ -0,0 +1,11 @@ +import { Logger } from 'tslog'; + +export const logger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + maskAnyRegEx: ['--token [A-Z0-9]*'], + minLevel: process.env.LOG_LEVEL || 'info', + name: 'scale-up', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); diff --git a/modules/runners/lambdas/runners/src/scale-runners/runners.ts b/modules/runners/lambdas/runners/src/scale-runners/runners.ts index e3892c1dab..2fea5f4cfa 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/runners.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/runners.ts @@ -1,4 +1,7 @@ import { EC2, SSM } from 'aws-sdk'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); export interface RunnerList { instanceId: string; @@ -72,16 +75,16 @@ export async function terminateRunner(instanceId: string): Promise { InstanceIds: [instanceId], }) .promise(); - console.debug(`Runner ${instanceId} has been terminated.`); + logger.debug(`Runner ${instanceId} has been terminated.`); } export async function createRunner(runnerParameters: RunnerInputParameters, launchTemplateName: string): Promise { - console.debug('Runner configuration: ' + JSON.stringify(runnerParameters)); + logger.debug('Runner configuration: ' + JSON.stringify(runnerParameters)); const ec2 = new EC2(); const runInstancesResponse = await ec2 .runInstances(getInstanceParams(launchTemplateName, runnerParameters)) .promise(); - console.info('Created instance(s): ', runInstancesResponse.Instances?.map((i) => i.InstanceId).join(',')); + logger.info('Created instance(s): ', runInstancesResponse.Instances?.map((i) => i.InstanceId).join(',')); const ssm = new SSM(); runInstancesResponse.Instances?.forEach(async (i: EC2.Instance) => { await ssm diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts b/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts index d949791d30..c369f87273 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts @@ -4,17 +4,20 @@ import { listEC2Runners, RunnerInfo, RunnerList, terminateRunner } from './runne import { getIdleRunnerCount, ScalingDownConfig } from './scale-down-config'; import { createOctoClient, createGithubAppAuth, createGithubInstallationAuth } from './gh-auth'; import { githubCache, GhRunners } from './cache'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); async function getOrCreateOctokit(runner: RunnerInfo): Promise { const key = runner.owner; const cachedOctokit = githubCache.clients.get(key); if (cachedOctokit) { - console.debug(`[createGitHubClientForRunner] Cache hit for ${key}`); + logger.debug(`[createGitHubClientForRunner] Cache hit for ${key}`); return cachedOctokit; } - console.debug(`[createGitHubClientForRunner] Cache miss for ${key}`); + logger.debug(`[createGitHubClientForRunner] Cache miss for ${key}`); const ghesBaseUrl = process.env.GHES_URL; let ghesApiUrl = ''; if (ghesBaseUrl) { @@ -47,12 +50,12 @@ async function listGitHubRunners(runner: RunnerInfo): Promise { const key = runner.owner as string; const cachedRunners = githubCache.runners.get(key); if (cachedRunners) { - console.debug(`[listGithubRunners] Cache hit for ${key}`); + logger.debug(`[listGithubRunners] Cache hit for ${key}`); return cachedRunners; } const client = await getOrCreateOctokit(runner); - console.debug(`[listGithubRunners] Cache miss for ${key}`); + logger.debug(`[listGithubRunners] Cache miss for ${key}`); const runners = runner.type === 'Org' ? await client.paginate(client.actions.listSelfHostedRunnersForOrg, { @@ -99,12 +102,12 @@ async function removeRunner(ec2runner: RunnerInfo, ghRunnerId: number): Promise< if (result.status == 204) { await terminateRunner(ec2runner.instanceId); - console.info(`AWS runner instance '${ec2runner.instanceId}' is terminated and GitHub runner is de-registered.`); + logger.info(`AWS runner instance '${ec2runner.instanceId}' is terminated and GitHub runner is de-registered.`); } else { - console.error(`Failed to de-register GitHub runner: ${result.status}`); + logger.error(`Failed to de-register GitHub runner: ${result.status}`); } } catch (e) { - console.debug(`Runner '${ec2runner.instanceId}' cannot be de-registered, most likely the runner is active.`); + logger.debug(`Runner '${ec2runner.instanceId}' cannot be de-registered, most likely the runner is active.`); } } @@ -117,7 +120,7 @@ async function evaluateAndRemoveRunners( for (const ownerTag of ownerTags) { const ec2RunnersFiltered = ec2Runners.filter((runner) => runner.owner === ownerTag); - console.debug(`Found: '${ec2RunnersFiltered.length}' active GitHub runners with owner tag: '${ownerTag}'`); + logger.debug(`Found: '${ec2RunnersFiltered.length}' active GitHub runners with owner tag: '${ownerTag}'`); for (const ec2Runner of ec2RunnersFiltered) { const ghRunners = await listGitHubRunners(ec2Runner); const ghRunner = ghRunners.find((runner) => runner.name === ec2Runner.instanceId); @@ -125,18 +128,18 @@ async function evaluateAndRemoveRunners( if (runnerMinimumTimeExceeded(ec2Runner)) { if (idleCounter > 0) { idleCounter--; - console.debug(`Runner '${ec2Runner.instanceId}' will kept idle.`); + logger.debug(`Runner '${ec2Runner.instanceId}' will kept idle.`); } else { - console.debug(`Runner '${ec2Runner.instanceId}' will be terminated.`); + logger.debug(`Runner '${ec2Runner.instanceId}' will be terminated.`); await removeRunner(ec2Runner, ghRunner.id); } } } else { if (bootTimeExceeded(ec2Runner)) { - console.debug(`Runner '${ec2Runner.instanceId}' is orphaned and will be removed.`); + logger.debug(`Runner '${ec2Runner.instanceId}' is orphaned and will be removed.`); terminateOrphan(ec2Runner.instanceId); } else { - console.debug(`Runner ${ec2Runner.instanceId} has not yet booted.`); + logger.debug(`Runner ${ec2Runner.instanceId} has not yet booted.`); } } } @@ -147,7 +150,7 @@ async function terminateOrphan(instanceId: string): Promise { try { await terminateRunner(instanceId); } catch (e) { - console.debug(`Orphan runner '${instanceId}' cannot be removed.`); + logger.debug(`Orphan runner '${instanceId}' cannot be removed.`); } } @@ -192,19 +195,19 @@ export async function scaleDown(): Promise { // list and sort runners, newest first. This ensure we keep the newest runners longer. const ec2Runners = await listAndSortRunners(environment); const activeEc2RunnersCount = ec2Runners.length; - console.info(`Found: '${activeEc2RunnersCount}' active GitHub EC2 runner instances before clean-up.`); + logger.info(`Found: '${activeEc2RunnersCount}' active GitHub EC2 runner instances before clean-up.`); if (activeEc2RunnersCount === 0) { - console.debug(`No active runners found for environment: '${environment}'`); + logger.debug(`No active runners found for environment: '${environment}'`); return; } const legacyRunners = filterLegacyRunners(ec2Runners); - console.debug(JSON.stringify(legacyRunners)); + logger.debug(JSON.stringify(legacyRunners)); const runners = filterRunners(ec2Runners); await evaluateAndRemoveRunners(runners, scaleDownConfigs); await evaluateAndRemoveRunners(legacyRunners, scaleDownConfigs); const activeEc2RunnersCountAfter = (await listAndSortRunners(environment)).length; - console.info(`Found: '${activeEc2RunnersCountAfter}' active GitHub EC2 runners instances after clean-up.`); + logger.info(`Found: '${activeEc2RunnersCountAfter}' active GitHub EC2 runners instances after clean-up.`); } diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts b/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts index 62e1f8a09e..a0a38d3ec4 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts @@ -2,6 +2,9 @@ import { listEC2Runners, createRunner, RunnerInputParameters } from './runners'; import { createOctoClient, createGithubAppAuth, createGithubInstallationAuth } from './gh-auth'; import yn from 'yn'; import { Octokit } from '@octokit/rest'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); export interface ActionRequestMessage { id: number; @@ -11,7 +14,7 @@ export interface ActionRequestMessage { installationId: number; } -export const scaleUp = async (eventSource: string, payload: ActionRequestMessage): Promise => { +export async function scaleUp(eventSource: string, payload: ActionRequestMessage): Promise { if (eventSource !== 'aws:sqs') throw Error('Cannot handle non-SQS events!'); const enableOrgLevel = yn(process.env.ENABLE_ORGANIZATION_RUNNERS, { default: true }); const maximumRunners = parseInt(process.env.RUNNERS_MAXIMUM_COUNT || '3'); @@ -55,7 +58,7 @@ export const scaleUp = async (eventSource: string, payload: ActionRequestMessage runnerType, runnerOwner, }); - console.info(`${runnerType} ${runnerOwner} has ${currentRunners.length}/${maximumRunners} runners`); + logger.info(`${runnerType} ${runnerOwner} has ${currentRunners.length}/${maximumRunners} runners`); if (currentRunners.length < maximumRunners) { // create token @@ -81,10 +84,10 @@ export const scaleUp = async (eventSource: string, payload: ActionRequestMessage runnerType, }); } else { - console.info('No runner will be created, maximum number of runners reached.'); + logger.info('No runner will be created, maximum number of runners reached.'); } } -}; +} async function getJobStatus(githubInstallationClient: Octokit, payload: ActionRequestMessage): Promise { let isQueued = false; @@ -105,7 +108,7 @@ async function getJobStatus(githubInstallationClient: Octokit, payload: ActionRe } else { throw Error(`Event ${payload.eventType} is not supported`); } - console.debug(`Job ${payload.id} is ${isQueued ? 'queued' : 'not queued'}`); + logger.debug(`Job ${payload.id} is ${isQueued ? 'queued' : 'not queued'}`); return isQueued; } @@ -113,14 +116,14 @@ export async function createRunnerLoop(runnerParameters: RunnerInputParameters): const launchTemplateNames = process.env.LAUNCH_TEMPLATE_NAME?.split(',') as string[]; let launched = false; for (let i = 0; i < launchTemplateNames.length; i++) { - console.info(`Attempt '${i}' to launch instance using ${launchTemplateNames[i]}.`); + logger.info(`Attempt '${i}' to launch instance using ${launchTemplateNames[i]}.`); try { await createRunner(runnerParameters, launchTemplateNames[i]); launched = true; break; } catch (error) { - console.debug(`Attempt '${i}' to launch instance using ${launchTemplateNames[i]} FAILED.`); - console.error(error); + logger.debug(`Attempt '${i}' to launch instance using ${launchTemplateNames[i]} FAILED.`); + logger.error(error); } } if (launched == false) { diff --git a/modules/runners/lambdas/runners/tsconfig.json b/modules/runners/lambdas/runners/tsconfig.json index 71f5cd6a47..764f2f6ae0 100644 --- a/modules/runners/lambdas/runners/tsconfig.json +++ b/modules/runners/lambdas/runners/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "outDir": "build", "lib": [ @@ -57,7 +57,8 @@ /* Experimental Options */ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true + "resolveJsonModule": true, + "sourceMap": true }, "include": [ "src/**/*" diff --git a/modules/webhook/lambdas/webhook/src/lambda.ts b/modules/webhook/lambdas/webhook/src/lambda.ts index af0f980df7..025c39fd91 100644 --- a/modules/webhook/lambdas/webhook/src/lambda.ts +++ b/modules/webhook/lambdas/webhook/src/lambda.ts @@ -1,19 +1,10 @@ import { handle } from './webhook/handler'; import { APIGatewayEvent, Context, Callback } from 'aws-lambda'; -import { Logger } from 'tslog'; - -export const rootLogger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - minLevel: process.env.LOG_LEVEL || 'info', - name: 'webhook', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', -}); +import { logger } from './webhook/logger'; export const githubWebhook = async (event: APIGatewayEvent, context: Context, callback: Callback): Promise => { - rootLogger.setSettings({ requestId: context.awsRequestId }); - rootLogger.debug(JSON.stringify(event)); + logger.setSettings({ requestId: context.awsRequestId }); + logger.debug(JSON.stringify(event)); try { const statusCode = await handle(event.headers, event.body); callback(null, { diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts index 401c53d8fc..237a2da875 100644 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts +++ b/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts @@ -26,6 +26,7 @@ describe('handler', () => { originalError = console.error; console.error = jest.fn(); jest.clearAllMocks(); + jest.resetAllMocks(); const mockedGet = mocked(getParameterValue); mockedGet.mockResolvedValueOnce(GITHUB_APP_WEBHOOK_SECRET); diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.ts index c3552f7fad..34661141f9 100644 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.ts +++ b/modules/webhook/lambdas/webhook/src/webhook/handler.ts @@ -3,6 +3,9 @@ import { Webhooks } from '@octokit/webhooks'; import { sendActionRequest } from '../sqs'; import { CheckRunEvent } from '@octokit/webhooks-types'; import { getParameterValue } from '../ssm'; +import { logger as rootLogger } from './logger'; + +const logger = rootLogger.getChildLogger(); // Event type not available yet in SDK export interface WorkflowJob { @@ -27,7 +30,7 @@ export interface WorkflowJob { }; } -export const handle = async (headers: IncomingHttpHeaders, payload: any): Promise => { +export async function handle(headers: IncomingHttpHeaders, payload: any): Promise { // ensure header keys lower case since github headers can contain capitals. for (const key in headers) { headers[key.toLowerCase()] = headers[key]; @@ -35,7 +38,7 @@ export const handle = async (headers: IncomingHttpHeaders, payload: any): Promis const signature = headers['x-hub-signature'] as string; if (!signature) { - console.error("Github event doesn't have signature. This webhook requires a secret to be configured."); + logger.error("Github event doesn't have signature. This webhook requires a secret to be configured."); return 500; } @@ -45,13 +48,13 @@ export const handle = async (headers: IncomingHttpHeaders, payload: any): Promis secret: secret, }); if (!(await webhooks.verify(payload as string, signature))) { - console.error('Unable to verify signature!'); + logger.error('Unable to verify signature!'); return 401; } const githubEvent = headers['x-github-event'] as string; - console.debug(`Received Github event: "${githubEvent}"`); + logger.debug(`Received Github event: "${githubEvent}"`); let status = 200; if (githubEvent == 'workflow_job') { @@ -59,22 +62,22 @@ export const handle = async (headers: IncomingHttpHeaders, payload: any): Promis } else if (githubEvent == 'check_run') { status = await handleCheckRun(JSON.parse(payload) as CheckRunEvent, githubEvent); } else { - console.debug('Ignore event ' + githubEvent); + logger.debug('Ignore event ' + githubEvent); } return status; -}; +} async function handleWorkflowJob(body: WorkflowJob, githubEvent: string): Promise { if (isRepoNotAllowed(body)) { - console.error(`Received event from unauthorized repository ${body.repository.full_name}`); + logger.error(`Received event from unauthorized repository ${body.repository.full_name}`); return 403; } const disableCheckWorkflowJobLabelsEnv = process.env.DISABLE_CHECK_WORKFLOW_JOB_LABELS || 'false'; const disableCheckWorkflowJobLabels = JSON.parse(disableCheckWorkflowJobLabelsEnv) as boolean; if (!disableCheckWorkflowJobLabels && !canRunJob(body)) { - console.error(`Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`); + logger.error(`Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`); return 403; } @@ -96,7 +99,7 @@ async function handleWorkflowJob(body: WorkflowJob, githubEvent: string): Promis async function handleCheckRun(body: CheckRunEvent, githubEvent: string): Promise { if (isRepoNotAllowed(body)) { - console.error(`Received event from unauthorized repository ${body.repository.full_name}`); + logger.error(`Received event from unauthorized repository ${body.repository.full_name}`); return 403; } @@ -139,7 +142,7 @@ function canRunJob(job: WorkflowJob): boolean { const runnerMatch = customWorkflowJobLabels.every((l) => runnerLabels.has(l)); - console.debug( + logger.debug( `Received workflow job event with labels: '${JSON.stringify(job.workflow_job.labels)}'. The event does ${ runnerMatch ? '' : 'NOT ' }match the configured labels: '${Array.from(runnerLabels).join(',')}'`, diff --git a/modules/webhook/lambdas/webhook/src/webhook/logger.ts b/modules/webhook/lambdas/webhook/src/webhook/logger.ts new file mode 100644 index 0000000000..b77bddf597 --- /dev/null +++ b/modules/webhook/lambdas/webhook/src/webhook/logger.ts @@ -0,0 +1,10 @@ +import { Logger } from 'tslog'; + +export const logger = new Logger({ + colorizePrettyLogs: false, + displayInstanceName: false, + minLevel: process.env.LOG_LEVEL || 'info', + name: 'webhook', + overwriteConsole: true, + type: process.env.LOG_TYPE || 'pretty', +}); diff --git a/modules/webhook/lambdas/webhook/tsconfig.json b/modules/webhook/lambdas/webhook/tsconfig.json index 64a2b54f25..764f2f6ae0 100644 --- a/modules/webhook/lambdas/webhook/tsconfig.json +++ b/modules/webhook/lambdas/webhook/tsconfig.json @@ -1,10 +1,13 @@ { "compilerOptions": { /* Basic Options */ - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "outDir": "build", - "lib": ["es2020", "DOM"] /* Specify library files to be included in the compilation. */, + "lib": [ + "es2020", + "DOM" + ] /* Specify library files to be included in the compilation. */, "allowJs": true /* Allow javascript files to be compiled. */, // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ @@ -54,7 +57,10 @@ /* Experimental Options */ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true + "resolveJsonModule": true, + "sourceMap": true }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/modules/webhook/lambdas/webhook/yarn.lock b/modules/webhook/lambdas/webhook/yarn.lock index 6eb275558a..ba9d6133fe 100644 --- a/modules/webhook/lambdas/webhook/yarn.lock +++ b/modules/webhook/lambdas/webhook/yarn.lock @@ -4160,7 +4160,7 @@ source-map-support@^0.5.12, source-map-support@^0.5.17: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.19: +source-map-support@^0.5.19, source-map-support@^0.5.6: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= @@ -4168,11 +4168,6 @@ source-map-support@^0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" From 6ad0ec3e90078c1345e5076b660a3815ec1fb0d8 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Fri, 22 Oct 2021 11:18:54 -0400 Subject: [PATCH 11/13] Resolving merge from develop Wouldn't be a conflict resolve without a miss --- modules/webhook/lambdas/webhook/src/webhook/handler.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.ts index 09c10ce439..f70aaca989 100644 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.ts +++ b/modules/webhook/lambdas/webhook/src/webhook/handler.ts @@ -7,7 +7,7 @@ import { logger as rootLogger } from './logger'; const logger = rootLogger.getChildLogger(); -export async function handle(headers: IncomingHttpHeaders, payload: any): Promise { +export async function handle(headers: IncomingHttpHeaders, body: string): Promise { // ensure header keys lower case since github headers can contain capitals. for (const key in headers) { headers[key.toLowerCase()] = headers[key]; @@ -38,7 +38,6 @@ export async function handle(headers: IncomingHttpHeaders, payload: any): Promis return status; } - async function verifySignature(githubEvent: string, signature: string, body: string): Promise { if (!signature) { logger.error("Github event doesn't have signature. This webhook requires a secret to be configured."); From 8bb29de76044b92f7c6f2b608fcc9b5ddc340f55 Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Mon, 25 Oct 2021 12:08:18 -0400 Subject: [PATCH 12/13] Logging when job is not queued --- modules/runners/lambdas/runners/src/scale-runners/scale-up.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts b/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts index 41ee3c3fc9..81da1e8794 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts +++ b/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts @@ -111,7 +111,9 @@ async function getJobStatus(githubInstallationClient: Octokit, payload: ActionRe } else { throw Error(`Event ${payload.eventType} is not supported`); } - logger.debug(`Job ${payload.id} is ${isQueued ? 'queued' : 'not queued'}`); + if (!isQueued) { + logger.info(`Job ${payload.id} is not queued`); + } return isQueued; } From 96890dca5b03013b4a66bd2d4a2cde72c3c47bbb Mon Sep 17 00:00:00 2001 From: Nathaniel McAuliffe Date: Mon, 25 Oct 2021 12:10:34 -0400 Subject: [PATCH 13/13] Updating handler names --- modules/runners/README.md | 184 ++++++++++++++++++---------------- modules/runners/scale-down.tf | 2 +- modules/runners/scale-up.tf | 2 +- 3 files changed, 102 insertions(+), 86 deletions(-) diff --git a/modules/runners/README.md b/modules/runners/README.md index dbfbd7fdd3..b7d52ff17e 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -52,111 +52,127 @@ yarn run dist | Name | Version | |------|---------| -| terraform | >= 0.14.1 | -| aws | >= 3.38 | +| [terraform](#requirement\_terraform) | >= 0.14.1 | +| [aws](#requirement\_aws) | >= 3.38 | ## Providers | Name | Version | |------|---------| -| aws | >= 3.38 | +| [aws](#provider\_aws) | >= 3.38 | ## Modules -No Modules. +No modules. ## Resources -| Name | -|------| -| [aws_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | -| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | -| [aws_cloudwatch_event_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | -| [aws_cloudwatch_event_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | -| [aws_cloudwatch_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | -| [aws_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | -| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | -| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | -| [aws_iam_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | -| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | -| [aws_lambda_event_source_mapping](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_event_source_mapping) | -| [aws_lambda_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | -| [aws_lambda_permission](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | -| [aws_launch_template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | -| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | -| [aws_ssm_parameter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | +| Name | Type | +|------|------| +| [aws_cloudwatch_event_rule.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_log_group.gh_runners](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_instance_profile.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_role.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.dist_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.runner_session_manager_aws_managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_down_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_up_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.service_linked_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.ssm_parameters](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.scale_down_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.scale_up_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_event_source_mapping.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_event_source_mapping) | resource | +| [aws_lambda_function.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_function.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_permission.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_lambda_permission.scale_runners_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_launch_template.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_security_group.runner_sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_ssm_parameter.cloudwatch_agent_config_runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [aws_ami.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| ami\_filter | Map of lists used to create the AMI filter for the action runner AMI. | `map(list(string))` |
{
"name": [
"amzn2-ami-hvm-2.*-x86_64-ebs"
]
}
| no | -| ami\_owners | The list of owners used to select the AMI of action runner instances. | `list(string)` |
[
"amazon"
]
| no | -| aws\_region | AWS region. | `string` | n/a | yes | -| block\_device\_mappings | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops` | `map(string)` | `{}` | no | -| 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. | `string` | `null` | no | -| create\_service\_linked\_role\_spot | (optional) create the service linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | -| egress\_rules | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | -| enable\_cloudwatch\_agent | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no | -| enable\_organization\_runners | n/a | `bool` | n/a | yes | -| enable\_ssm\_on\_runners | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes | -| environment | A name that identifies the environment, used as prefix and for tagging. | `string` | n/a | yes | -| ghes\_ssl\_verify | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | -| ghes\_url | GitHub Enterprise Server URL. DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | -| github\_app\_parameters | Parameter Store for GitHub App Parameters. |
object({
key_base64 = map(string)
id = map(string)
})
| n/a | yes | -| idle\_config | List of time period that can be defined as 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. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | -| 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 | -| instance\_type | [DEPRECATED] See instance\_types. | `string` | `"m5.large"` | no | -| instance\_types | List of instance types for the action runner. | `list(string)` | `null` | no | -| key\_name | Key pair name | `string` | `null` | no | -| kms\_key\_arn | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | -| lambda\_s3\_bucket | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | -| lambda\_security\_group\_ids | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | -| lambda\_subnet\_ids | List of subnets in which the lambda will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | -| lambda\_timeout\_scale\_down | Time out for the scale down lambda in seconds. | `number` | `60` | no | -| lambda\_timeout\_scale\_up | Time out for the scale up lambda in seconds. | `number` | `60` | no | -| lambda\_zip | File location of the lambda zip file. | `string` | `null` | no | -| log\_level | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | -| log\_type | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | -| logging\_retention\_in\_days | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | -| market\_options | Market options for the action runner instances. | `string` | `"spot"` | no | -| minimum\_running\_time\_in\_minutes | The time an ec2 action runner should be running at minimum before terminated if non busy. | `number` | `5` | no | -| 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)` |
{
"name_runner": "",
"name_sg": ""
}
| no | -| role\_path | The path that will be added to the role; if not set, the environment name will be used. | `string` | `null` | no | -| role\_permissions\_boundary | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | -| runner\_additional\_security\_group\_ids | (optional) List of additional security groups IDs to apply to the runner | `list(string)` | `[]` | no | -| runner\_architecture | The platform architecture of the runner instance\_type. | `string` | `"x64"` | no | -| runner\_as\_root | Run the action runner under the root user. | `bool` | `false` | no | -| runner\_boot\_time\_in\_minutes | The minimum time for an EC2 runner to boot and register as a runner. | `number` | `5` | no | -| runner\_extra\_labels | Extra labels for the runners (GitHub). Separate each label by a comma | `string` | `""` | no | -| runner\_group\_name | Name of the runner group. | `string` | `"Default"` | no | -| runner\_iam\_role\_managed\_policy\_arns | Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role | `list(string)` | `[]` | no | -| 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/`, `file_path`: path to the log file, `log_stream_name`: name of the log stream. |
list(object({
log_group_name = string
prefix_log_group = bool
file_path = string
log_stream_name = string
}))
|
[
{
"file_path": "/var/log/messages",
"log_group_name": "messages",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
},
{
"file_path": "/var/log/user-data.log",
"log_group_name": "user_data",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
},
{
"file_path": "/home/ec2-user/actions-runner/_diag/Runner_**.log",
"log_group_name": "runner",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
}
]
| no | -| runners\_lambda\_s3\_key | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| runners\_lambda\_s3\_object\_version | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | -| runners\_maximum\_count | The maximum number of runners that will be created. | `number` | `3` | no | -| s3\_bucket\_runner\_binaries | n/a |
object({
arn = string
})
| n/a | yes | -| s3\_location\_runner\_binaries | S3 location of runner distribution. | `string` | n/a | yes | -| scale\_down\_schedule\_expression | Scheduler expression to check every x for scale down. | `string` | `"cron(*/5 * * * ? *)"` | no | -| sqs\_build\_queue | SQS queue to consume accepted build events. |
object({
arn = string
})
| n/a | yes | -| subnet\_ids | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | n/a | yes | -| tags | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | -| userdata\_post\_install | User-data script snippet to insert after GitHub action runner install | `string` | `""` | no | -| userdata\_pre\_install | User-data script snippet to insert before GitHub action runner install | `string` | `""` | no | -| userdata\_template | Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | -| volume\_size | Size of runner volume | `number` | `30` | no | -| vpc\_id | The VPC for the security groups. | `string` | n/a | yes | +| [ami\_filter](#input\_ami\_filter) | Map of lists used to create the AMI filter for the action runner AMI. | `map(list(string))` |
{
"name": [
"amzn2-ami-hvm-2.*-x86_64-ebs"
]
}
| no | +| [ami\_owners](#input\_ami\_owners) | The list of owners used to select the AMI of action runner instances. | `list(string)` |
[
"amazon"
]
| no | +| [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | +| [block\_device\_mappings](#input\_block\_device\_mappings) | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops` | `map(string)` | `{}` | no | +| [cloudwatch\_config](#input\_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. | `string` | `null` | no | +| [create\_service\_linked\_role\_spot](#input\_create\_service\_linked\_role\_spot) | (optional) create the service linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | +| [egress\_rules](#input\_egress\_rules) | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | +| [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no | +| [enable\_organization\_runners](#input\_enable\_organization\_runners) | n/a | `bool` | n/a | yes | +| [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes | +| [environment](#input\_environment) | A name that identifies the environment, used as prefix and for tagging. | `string` | n/a | yes | +| [ghes\_ssl\_verify](#input\_ghes\_ssl\_verify) | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | +| [ghes\_url](#input\_ghes\_url) | GitHub Enterprise Server URL. DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | +| [github\_app\_parameters](#input\_github\_app\_parameters) | Parameter Store for GitHub App Parameters. |
object({
key_base64 = map(string)
id = map(string)
})
| n/a | yes | +| [idle\_config](#input\_idle\_config) | List of time period that can be defined as 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. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | +| [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 | +| [instance\_type](#input\_instance\_type) | [DEPRECATED] See instance\_types. | `string` | `"m5.large"` | no | +| [instance\_types](#input\_instance\_types) | List of instance types for the action runner. | `list(string)` | `null` | no | +| [key\_name](#input\_key\_name) | Key pair name | `string` | `null` | no | +| [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | +| [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | +| [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the lambda will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_timeout\_scale\_down](#input\_lambda\_timeout\_scale\_down) | Time out for the scale down lambda in seconds. | `number` | `60` | no | +| [lambda\_timeout\_scale\_up](#input\_lambda\_timeout\_scale\_up) | Time out for the scale up lambda in seconds. | `number` | `60` | no | +| [lambda\_zip](#input\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | +| [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | +| [log\_type](#input\_log\_type) | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | +| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | +| [market\_options](#input\_market\_options) | Market options for the action runner instances. | `string` | `"spot"` | no | +| [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. | `number` | `5` | no | +| [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)` |
{
"name_runner": "",
"name_sg": ""
}
| no | +| [role\_path](#input\_role\_path) | The path that will be added to the role; if not set, the environment name will be used. | `string` | `null` | no | +| [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | +| [runner\_additional\_security\_group\_ids](#input\_runner\_additional\_security\_group\_ids) | (optional) List of additional security groups IDs to apply to the runner | `list(string)` | `[]` | no | +| [runner\_architecture](#input\_runner\_architecture) | The platform architecture of the runner instance\_type. | `string` | `"x64"` | no | +| [runner\_as\_root](#input\_runner\_as\_root) | Run the action runner under the root user. | `bool` | `false` | no | +| [runner\_boot\_time\_in\_minutes](#input\_runner\_boot\_time\_in\_minutes) | The minimum time for an EC2 runner to boot and register as a runner. | `number` | `5` | no | +| [runner\_extra\_labels](#input\_runner\_extra\_labels) | Extra labels for the runners (GitHub). Separate each label by a comma | `string` | `""` | no | +| [runner\_group\_name](#input\_runner\_group\_name) | Name of the runner group. | `string` | `"Default"` | no | +| [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 | +| [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/`, `file_path`: path to the log file, `log_stream_name`: name of the log stream. |
list(object({
log_group_name = string
prefix_log_group = bool
file_path = string
log_stream_name = string
}))
|
[
{
"file_path": "/var/log/messages",
"log_group_name": "messages",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
},
{
"file_path": "/var/log/user-data.log",
"log_group_name": "user_data",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
},
{
"file_path": "/home/ec2-user/actions-runner/_diag/Runner_**.log",
"log_group_name": "runner",
"log_stream_name": "{instance_id}",
"prefix_log_group": true
}
]
| no | +| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | +| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | +| [runners\_maximum\_count](#input\_runners\_maximum\_count) | The maximum number of runners that will be created. | `number` | `3` | no | +| [s3\_bucket\_runner\_binaries](#input\_s3\_bucket\_runner\_binaries) | n/a |
object({
arn = string
})
| n/a | yes | +| [s3\_location\_runner\_binaries](#input\_s3\_location\_runner\_binaries) | S3 location of runner distribution. | `string` | n/a | yes | +| [scale\_down\_schedule\_expression](#input\_scale\_down\_schedule\_expression) | Scheduler expression to check every x for scale down. | `string` | `"cron(*/5 * * * ? *)"` | no | +| [sqs\_build\_queue](#input\_sqs\_build\_queue) | SQS queue to consume accepted build events. |
object({
arn = string
})
| n/a | yes | +| [subnet\_ids](#input\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | n/a | yes | +| [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [userdata\_post\_install](#input\_userdata\_post\_install) | User-data script snippet to insert after GitHub action runner install | `string` | `""` | no | +| [userdata\_pre\_install](#input\_userdata\_pre\_install) | User-data script snippet to insert before GitHub action runner install | `string` | `""` | no | +| [userdata\_template](#input\_userdata\_template) | Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | +| [volume\_size](#input\_volume\_size) | Size of runner volume | `number` | `30` | no | +| [vpc\_id](#input\_vpc\_id) | The VPC for the security groups. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| lambda\_scale\_down | n/a | -| lambda\_scale\_up | n/a | -| launch\_template | n/a | -| role\_runner | n/a | -| role\_scale\_down | n/a | -| role\_scale\_up | n/a | +| [lambda\_scale\_down](#output\_lambda\_scale\_down) | n/a | +| [lambda\_scale\_up](#output\_lambda\_scale\_up) | n/a | +| [launch\_template](#output\_launch\_template) | n/a | +| [role\_runner](#output\_role\_runner) | n/a | +| [role\_scale\_down](#output\_role\_scale\_down) | n/a | +| [role\_scale\_up](#output\_role\_scale\_up) | n/a | ## Philips Forest diff --git a/modules/runners/scale-down.tf b/modules/runners/scale-down.tf index c3e68cefd4..d3cb5beb37 100644 --- a/modules/runners/scale-down.tf +++ b/modules/runners/scale-down.tf @@ -6,7 +6,7 @@ resource "aws_lambda_function" "scale_down" { source_code_hash = var.lambda_s3_bucket == null ? filebase64sha256(local.lambda_zip) : null function_name = "${var.environment}-scale-down" role = aws_iam_role.scale_down.arn - handler = "index.scaleDown" + handler = "index.scaleDownHandler" runtime = "nodejs14.x" timeout = var.lambda_timeout_scale_down tags = local.tags diff --git a/modules/runners/scale-up.tf b/modules/runners/scale-up.tf index 07a2de3bf6..cb61dde66a 100644 --- a/modules/runners/scale-up.tf +++ b/modules/runners/scale-up.tf @@ -6,7 +6,7 @@ resource "aws_lambda_function" "scale_up" { source_code_hash = var.lambda_s3_bucket == null ? filebase64sha256(local.lambda_zip) : null function_name = "${var.environment}-scale-up" role = aws_iam_role.scale_up.arn - handler = "index.scaleUp" + handler = "index.scaleUpHandler" runtime = "nodejs14.x" timeout = var.lambda_timeout_scale_up reserved_concurrent_executions = 1