UNPKG

@cloudsnorkel/cdk-github-runners

Version:

CDK construct to create GitHub Actions self-hosted runners. Creates ephemeral runners on demand. Easy to deploy and highly customizable.

256 lines (255 loc) 9.06 kB
import * as cdk from 'aws-cdk-lib'; import { aws_ec2 as ec2, aws_ecs as ecs, aws_iam as iam, aws_logs as logs, aws_stepfunctions as stepfunctions } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { BaseProvider, IRunnerProvider, IRunnerProviderStatus, RunnerProviderProps, RunnerRuntimeParameters, StorageOptions } from './common'; import { IRunnerImageBuilder, RunnerImageBuilderProps } from '../image-builders'; /** * Properties for EcsRunnerProvider. */ export interface EcsRunnerProviderProps extends RunnerProviderProps { /** * Runner image builder used to build Docker images containing GitHub Runner and all requirements. * * The image builder determines the OS and architecture of the runner. * * @default EcsRunnerProvider.imageBuilder() */ readonly imageBuilder?: IRunnerImageBuilder; /** * GitHub Actions labels used for this provider. * * These labels are used to identify which provider should spawn a new on-demand runner. Every job sends a webhook with the labels it's looking for * based on runs-on. We match the labels from the webhook with the labels specified here. If all the labels specified here are present in the * job's labels, this provider will be chosen and spawn a new runner. * * @default ['ecs'] */ readonly labels?: string[]; /** * GitHub Actions runner group name. * * If specified, the runner will be registered with this group name. Setting a runner group can help managing access to self-hosted runners. It * requires a paid GitHub account. * * The group must exist or the runner will not start. * * Users will still be able to trigger this runner with the correct labels. But the runner will only be able to run jobs from repos allowed to use the group. * * @default undefined */ readonly group?: string; /** * VPC to launch the runners in. * * @default default account VPC */ readonly vpc?: ec2.IVpc; /** * Subnets to run the runners in. * * @default ECS default */ readonly subnetSelection?: ec2.SubnetSelection; /** * Security groups to assign to the task. * * @default a new security group */ readonly securityGroups?: ec2.ISecurityGroup[]; /** * Existing ECS cluster to use. * * @default a new cluster */ readonly cluster?: ecs.Cluster; /** * Existing capacity provider to use. * * Make sure the AMI used by the capacity provider is compatible with ECS. * * @default new capacity provider */ readonly capacityProvider?: ecs.AsgCapacityProvider; /** * Assign public IP to the runner task. * * Make sure the task will have access to GitHub. A public IP might be required unless you have NAT gateway. * * @default true */ readonly assignPublicIp?: boolean; /** * The number of cpu units used by the task. 1024 units is 1 vCPU. Fractions of a vCPU are supported. * * @default 1024 */ readonly cpu?: number; /** * The amount (in MiB) of memory used by the task. * * @default 3500, unless `memoryReservationMiB` is used and then it's undefined */ readonly memoryLimitMiB?: number; /** * The soft limit (in MiB) of memory to reserve for the container. * * @default undefined */ readonly memoryReservationMiB?: number; /** * Instance type of ECS cluster instances. Only used when creating a new cluster. * * @default m6i.large or m6g.large */ readonly instanceType?: ec2.InstanceType; /** * The minimum number of instances to run in the cluster. Only used when creating a new cluster. * * @default 0 */ readonly minInstances?: number; /** * The maximum number of instances to run in the cluster. Only used when creating a new cluster. * * @default 5 */ readonly maxInstances?: number; /** * Size of volume available for launched cluster instances. This modifies the boot volume size and doesn't add any additional volumes. * * Each instance can be used by multiple runners, so make sure there is enough space for all of them. * * @default default size for AMI (usually 30GB for Linux and 50GB for Windows) */ readonly storageSize?: cdk.Size; /** * Options for runner instance storage volume. */ readonly storageOptions?: StorageOptions; /** * Support building and running Docker images by enabling Docker-in-Docker (dind) and the required CodeBuild privileged mode. Disabling this can * speed up provisioning of CodeBuild runners. If you don't intend on running or building Docker images, disable this for faster start-up times. * * @default true */ readonly dockerInDocker?: boolean; /** * Use spot capacity. * * @default false (true if spotMaxPrice is specified) */ readonly spot?: boolean; /** * Maximum price for spot instances. */ readonly spotMaxPrice?: string; } /** * GitHub Actions runner provider using ECS on EC2 to execute jobs. * * ECS can be useful when you want more control of the infrastructure running the GitHub Actions Docker containers. You can control the autoscaling * group to scale down to zero during the night and scale up during work hours. This way you can still save money, but have to wait less for * infrastructure to spin up. * * This construct is not meant to be used by itself. It should be passed in the providers property for GitHubRunners. */ export declare class EcsRunnerProvider extends BaseProvider implements IRunnerProvider { /** * Create new image builder that builds ECS specific runner images. * * You can customize the OS, architecture, VPC, subnet, security groups, etc. by passing in props. * * You can add components to the image builder by calling `imageBuilder.addComponent()`. * * The default OS is Ubuntu running on x64 architecture. * * Included components: * * `RunnerImageComponent.requiredPackages()` * * `RunnerImageComponent.runnerUser()` * * `RunnerImageComponent.git()` * * `RunnerImageComponent.githubCli()` * * `RunnerImageComponent.awsCli()` * * `RunnerImageComponent.docker()` * * `RunnerImageComponent.githubRunner()` */ static imageBuilder(scope: Construct, id: string, props?: RunnerImageBuilderProps): import("../image-builders").IConfigurableRunnerImageBuilder; /** * Cluster hosting the task hosting the runner. */ private readonly cluster; /** * Capacity provider used to scale the cluster. */ private readonly capacityProvider; /** * ECS task hosting the runner. */ private readonly task; /** * Container definition hosting the runner. */ private readonly container; /** * Labels associated with this provider. */ readonly labels: string[]; /** * VPC used for hosting the runner task. */ private readonly vpc?; /** * Subnets used for hosting the runner task. */ private readonly subnetSelection?; /** * Whether runner task will have a public IP. */ private readonly assignPublicIp; /** * Grant principal used to add permissions to the runner role. */ readonly grantPrincipal: iam.IPrincipal; /** * The network connections associated with this resource. */ readonly connections: ec2.Connections; /** * Docker image loaded with GitHub Actions Runner and its prerequisites. The image is built by an image builder and is specific to ECS tasks. */ private readonly image; /** * Log group where provided runners will save their logs. * * Note that this is not the job log, but the runner itself. It will not contain output from the GitHub Action but only metadata on its execution. */ readonly logGroup: logs.ILogGroup; /** * Security groups associated with this provider. */ private readonly securityGroups; /** * Run docker in docker. */ private readonly dind; /** * Runner group name. */ private readonly group?; readonly retryableErrors: string[]; constructor(scope: Construct, id: string, props?: EcsRunnerProviderProps); private defaultClusterInstanceType; private defaultClusterInstanceAmi; private pullCommand; private loginCommands; private ecsSettingsCommands; /** * Generate step function task(s) to start a new runner. * * Called by GithubRunners and shouldn't be called manually. * * @param parameters workflow job details */ getStepFunctionTask(parameters: RunnerRuntimeParameters): stepfunctions.IChainable; grantStateMachine(_: iam.IGrantable): void; status(statusFunctionRole: iam.IGrantable): IRunnerProviderStatus; }