@cloudsnorkel/cdk-github-runners 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jsii CHANGED
@@ -3437,7 +3437,7 @@
3437
3437
  },
3438
3438
  "name": "@cloudsnorkel/cdk-github-runners",
3439
3439
  "readme": {
3440
- "markdown": "# GitHub Self-Hosted Runners CDK Constructs\n\n[![NPM](https://img.shields.io/npm/v/@cloudsnorkel/cdk-github-runners?label=npm&logo=npm)][7]\n[![PyPI](https://img.shields.io/pypi/v/cloudsnorkel.cdk-github-runners?label=pypi&logo=pypi)][6]\n[![Maven Central](https://img.shields.io/maven-central/v/com.cloudsnorkel/cdk.github.runners.svg?label=Maven%20Central&logo=apachemaven)][8]\n[![Go](https://img.shields.io/github/v/tag/CloudSnorkel/cdk-github-runners?color=red&label=go&logo=go)][11]\n[![Nuget](https://img.shields.io/nuget/v/CloudSnorkel.Cdk.Github.Runners?color=red&&logo=nuget)][12]\n[![Release](https://github.com/CloudSnorkel/cdk-github-runners/actions/workflows/release.yml/badge.svg)](https://github.com/CloudSnorkel/cdk-github-runners/actions/workflows/release.yml)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/CloudSnorkel/cdk-github-runners/blob/main/LICENSE)\n\nUse this CDK construct to create ephemeral [self-hosted GitHub runners][1] on-demand inside your AWS account.\n\n* Easy to configure GitHub integration with a web-based interface\n* Customizable runners with decent defaults\n* Multiple runner configurations controlled by labels\n* Everything fully hosted in your account\n* Automatically updated build environment with latest runner version\n\nSelf-hosted runners in AWS are useful when:\n\n* You need easy access to internal resources in your actions\n* You want to pre-install some software for your actions\n* You want to provide some basic AWS API access (but [aws-actions/configure-aws-credentials][2] has more security controls)\n* You are using GitHub Enterprise Server\n\nEphemeral (or on-demand) runners are the [recommended way by GitHub][14] for auto-scaling, and they make sure all jobs run with a clean image. Runners are started on-demand. You don't pay unless a job is running.\n\n## API\n\nThe best way to browse API documentation is on [Constructs Hub][13]. It is available in all supported programming languages.\n\n## Providers\n\nA runner provider creates compute resources on-demand and uses [actions/runner][5] to start a runner.\n\n| | EC2 | CodeBuild | Fargate | ECS | Lambda |\n|------------------|-------------------|----------------------------|----------------|----------------|---------------|\n| **Time limit** | Unlimited | 8 hours | Unlimited | Unlimited | 15 minutes |\n| **vCPUs** | Unlimited | 2, 4, 8, or 72 | 0.25 to 4 | Unlimited | 1 to 6 |\n| **RAM** | Unlimited | 3gb, 7gb, 15gb, or 145gb | 512mb to 30gb | Unlimited | 128mb to 10gb |\n| **Storage** | Unlimited | 50gb to 824gb | 20gb to 200gb | Unlimited | Up to 10gb |\n| **Architecture** | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 |\n| **sudo** | ✔ | ✔ | ✔ | ✔ | ❌ |\n| **Docker** | ✔ | ✔ (Linux only) | ❌ | ✔ | ❌ |\n| **Spot pricing** | ✔ | ❌ | ✔ | ✔ | ❌ |\n| **OS** | Linux, Windows | Linux, Windows | Linux, Windows | Linux, Windows | Linux |\n\nThe best provider to use mostly depends on your current infrastructure. When in doubt, CodeBuild is always a good choice. Execution history and logs are easy to view, and it has no restrictive limits unless you need to run for more than 8 hours.\n\n* EC2 is useful when you want runners to have complete access to the host\n* ECS is useful when you want to control the infrastructure, like leaving the runner host running for faster startups\n* Lambda is useful for short jobs that can work within time, size and readonly system constraints\n\nYou can also create your own provider by implementing `IRunnerProvider`.\n\n## Installation\n\n1. Install and use the appropriate package\n <details><summary>Python</summary>\n\n ### Install\n Available on [PyPI][6].\n ```bash\n pip install cloudsnorkel.cdk-github-runners\n ```\n ### Use\n ```python\n from cloudsnorkel.cdk_github_runners import GitHubRunners\n\n GitHubRunners(self, \"runners\")\n ```\n </details>\n <details><summary>TypeScript or JavaScript</summary>\n\n ### Install\n Available on [npm][7].\n ```bash\n npm i @cloudsnorkel/cdk-github-runners\n ```\n ### Use\n ```typescript\n import { GitHubRunners } from '@cloudsnorkel/cdk-github-runners';\n\n new GitHubRunners(this, \"runners\");\n ```\n </details>\n <details><summary>Java</summary>\n\n ### Install\n Available on [Maven][8].\n ```xml\n <dependency>\n <groupId>com.cloudsnorkel</groupId>\n <artifactId>cdk.github.runners</artifactId>\n </dependency>\n ```\n ### Use\n ```java\n import com.cloudsnorkel.cdk.github.runners.GitHubRunners;\n\n GitHubRunners.Builder.create(this, \"runners\").build();\n ```\n </details>\n <details><summary>Go</summary>\n\n ### Install\n Available on [GitHub][11].\n ```bash\n go get github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n ```\n ### Use\n ```go\n import \"github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\"\n\n NewGitHubRunners(this, jsii.String(\"runners\"))\n ```\n </details>\n <details><summary>.NET</summary>\n\n ### Install\n Available on [Nuget][12].\n ```bash\n dotnet add package CloudSnorkel.Cdk.Github.Runners\n ```\n ### Use\n ```csharp\n using CloudSnorkel;\n\n new GitHubRunners(this, \"runners\");\n ```\n </details>\n2. Use `GitHubRunners` construct in your code (starting with default arguments is fine)\n3. Deploy your stack\n4. Look for the status command output similar to `aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json`\n ```\n ✅ github-runners-test\n\n ✨ Deployment time: 260.01s\n\n Outputs:\n github-runners-test.runnersstatuscommand4A30F0F5 = aws --region us-east-1 lambda invoke --function-name github-runners-test-runnersstatus1A5771C0-mvttg8oPQnQS status.json\n ```\n5. Execute the status command (you may need to specify `--profile` too) and open the resulting `status.json` file\n6. Open the URL in `github.setup.url` from `status.json` or [manually setup GitHub](SETUP_GITHUB.md) integration as an app or with personal access token\n7. Run status command again to confirm `github.auth.status` and `github.webhook.status` are OK\n8. Trigger a GitHub action that has a `self-hosted` label with `runs-on: [self-hosted, linux, codebuild]` or similar\n9. If the action is not successful, see [troubleshooting](#Troubleshooting)\n\n[![Demo](demo-thumbnail.jpg)](https://youtu.be/wlyv_3V8lIw)\n\n## Customizing\n\nThe default providers configured by `GitHubRunners` are useful for testing but probably not too much for actual production work. They run in the default VPC or no VPC and have no added IAM permissions. You would usually want to configure the providers yourself.\n\nFor example:\n\n```typescript\nlet vpc: ec2.Vpc;\nlet runnerSg: ec2.SecurityGroup;\nlet dbSg: ec2.SecurityGroup;\nlet bucket: s3.Bucket;\n\n// create a custom CodeBuild provider\nconst myProvider = new CodeBuildRunnerProvider(this, 'codebuild runner', {\n labels: ['my-codebuild'],\n vpc: vpc,\n securityGroups: [runnerSg],\n});\n// grant some permissions to the provider\nbucket.grantReadWrite(myProvider);\ndbSg.connections.allowFrom(runnerSg, ec2.Port.tcp(3306), 'allow runners to connect to MySQL database');\n\n// create the runner infrastructure\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nAnother way to customize runners is by modifying the image used to spin them up. The image contains the [runner][5], any required dependencies, and integration code with the provider. You may choose to customize this image by adding more packages, for example.\n\n```typescript\nconst myBuilder = CodeBuildRunnerProvider.imageBuilder(this, 'image builder', {\n dockerfilePath: FargateRunner.LINUX_X64_DOCKERFILE_PATH,\n runnerVersion: RunnerVersion.specific('2.291.0'),\n rebuildInterval: Duration.days(14),\n});\nmyBuilder.addComponent(\n RunnerImageComponent.custom({ commands: ['apt install -y nginx xz-utils'] })\n);\n\nconst myProvider = new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['customized-fargate'],\n vpc: vpc,\n securityGroups: [runnerSg],\n imageBuilder: myBuilder,\n});\n\n// create the runner infrastructure\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nYour workflow will then look like:\n\n```yaml\nname: self-hosted example\non: push\njobs:\n self-hosted:\n runs-on: [self-hosted, customized-fargate]\n steps:\n - run: echo hello world\n```\n\nWindows images can also be customized the same way.\n\n```typescript\nconst myWindowsBuilder = FargateRunnerProvider.imageBuilder(this, 'Windows image builder', {\n architecture: Architecture.X86_64,\n os: Os.WINDOWS,\n runnerVersion: RunnerVersion.specific('2.291.0'),\n rebuildInterval: Duration.days(14),\n});\nmyWindowsBuilder.addComponent(\n RunnerImageComponent.custom({\n name: 'Ninja',\n commands: [\n 'Invoke-WebRequest -UseBasicParsing -Uri \"https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip\" -OutFile ninja.zip',\n 'Expand-Archive ninja.zip -DestinationPath C:\\\\actions',\n 'del ninja.zip',\n ],\n })\n);\n\nconst myProvider = new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['customized-windows-fargate'],\n vpc: vpc,\n securityGroups: [runnerSg],\n imageBuilder: myWindowsBuilder,\n});\n\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nThe runner OS and architecture is determined by the image it is set to use. For example, to create a Fargate runner provider for ARM64 set the `architecture` property for the image builder to `Architecture.ARM64` in the image builder properties.\n\n```typescript\nnew GitHubRunners(this, 'runners', {\n providers: [\n new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['arm64', 'fargate'],\n imageBuilder: FargateRunnerProvider.imageBuilder(this, 'image builder', {\n architecture: Architecture.ARM64,\n os: Os.LINUX_UBUNTU,\n }),\n }),\n ],\n});\n```\n\n## Architecture\n\n![Architecture diagram](architecture.svg)\n\n## Troubleshooting\n\nRunners are started in response to a webhook coming in from GitHub. If there are any issues starting the runner like missing capacity or transient API issues, the provider will keep retrying for 24 hours. Configuration issue related errors like pointing to a missing AMI will not be retried. GitHub itself will cancel the job if it can't find a runner for 24 hours. If your jobs don't start, follow the steps below to examine all parts of this workflow.\n\n1. Always start with the status function, make sure no errors are reported, and confirm all status codes are OK\n2. Make sure `runs-on` in the workflow matches the expected labels set in the runner provider\n3. Diagnose relevant executions of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`\n 1. If the execution failed, check your runner provider configuration for errors\n 2. If the execution is still running for a long time, check the execution events to see why runner starting is being retried\n 3. If there are no relevant executions, move to the next step\n4. Confirm the webhook Lambda was called by visiting the URL in `troubleshooting.webhookHandlerUrl` from `status.json`\n 1. If it's not called or logs errors, confirm the webhook settings on the GitHub side\n 2. If you see too many errors, make sure you're only sending `workflow_job` events\n5. When using GitHub app, make sure there are active installations in `github.auth.app.installations`\n\n## Monitoring\n\nThere are two important ways to monitor your runners:\n\n1. Make sure runners don't fail to start. When that happens, jobs may sit and wait. Use `GitHubRunners.metricFailed()` to get a metric for the number of failed runner starts. You should use this metric to trigger an alarm.\n2. Make sure runner images don't fail to build. Failed runner image builds mean you will get stuck with out-of-date software on your runners. It may lead to security vulnerabilities, or it may lead to slower runner start-ups as the runner software itself needs to be updated. Use `GitHubRunners.failedImageBuildsTopic()` to get SNS topic that gets notified of failed runner image builds. You should subscribe to this topic.\n\nOther useful metrics to track:\n\n1. Use `GitHubRunners.metricJobCompleted()` to get a metric for the number of completed jobs broken down by labels and job success.\n2. Use `GitHubRunners.metricTime()` to get a metric for the total time a runner is running. This includes the overhead of starting the runner.\n\n## Other Options\n\n1. [philips-labs/terraform-aws-github-runner][3] if you're using Terraform\n2. [actions/actions-runner-controller][4] if you're using Kubernetes\n\n\n[1]: https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners\n[2]: https://github.com/marketplace/actions/configure-aws-credentials-for-github-actions\n[3]: https://github.com/philips-labs/terraform-aws-github-runner\n[4]: https://github.com/actions/actions-runner-controller\n[5]: https://github.com/actions/runner\n[6]: https://pypi.org/project/cloudsnorkel.cdk-github-runners\n[7]: https://www.npmjs.com/package/@cloudsnorkel/cdk-github-runners\n[8]: https://central.sonatype.com/artifact/com.cloudsnorkel/cdk.github.runners/\n[9]: https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps\n[10]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token\n[11]: https://pkg.go.dev/github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n[12]: https://www.nuget.org/packages/CloudSnorkel.Cdk.Github.Runners/\n[13]: https://constructs.dev/packages/@cloudsnorkel/cdk-github-runners/\n[14]: https://docs.github.com/en/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#using-ephemeral-runners-for-autoscaling\n"
3440
+ "markdown": "# GitHub Self-Hosted Runners CDK Constructs\n\n[![NPM](https://img.shields.io/npm/v/@cloudsnorkel/cdk-github-runners?label=npm&logo=npm)][7]\n[![PyPI](https://img.shields.io/pypi/v/cloudsnorkel.cdk-github-runners?label=pypi&logo=pypi)][6]\n[![Maven Central](https://img.shields.io/maven-central/v/com.cloudsnorkel/cdk.github.runners.svg?label=Maven%20Central&logo=apachemaven)][8]\n[![Go](https://img.shields.io/github/v/tag/CloudSnorkel/cdk-github-runners?color=red&label=go&logo=go)][11]\n[![Nuget](https://img.shields.io/nuget/v/CloudSnorkel.Cdk.Github.Runners?color=red&&logo=nuget)][12]\n[![Release](https://github.com/CloudSnorkel/cdk-github-runners/actions/workflows/release.yml/badge.svg)](https://github.com/CloudSnorkel/cdk-github-runners/actions/workflows/release.yml)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/CloudSnorkel/cdk-github-runners/blob/main/LICENSE)\n\nUse this CDK construct to create ephemeral [self-hosted GitHub runners][1] on-demand inside your AWS account.\n\n* Easy to configure GitHub integration with a web-based interface\n* Customizable runners with decent defaults\n* Multiple runner configurations controlled by labels\n* Everything fully hosted in your account\n* Automatically updated build environment with latest runner version\n\nSelf-hosted runners in AWS are useful when:\n\n* You need easy access to internal resources in your actions\n* You want to pre-install some software for your actions\n* You want to provide some basic AWS API access (but [aws-actions/configure-aws-credentials][2] has more security controls)\n* You are using GitHub Enterprise Server\n\nEphemeral (or on-demand) runners are the [recommended way by GitHub][14] for auto-scaling, and they make sure all jobs run with a clean image. Runners are started on-demand. You don't pay unless a job is running.\n\n## API\n\nThe best way to browse API documentation is on [Constructs Hub][13]. It is available in all supported programming languages.\n\n## Providers\n\nA runner provider creates compute resources on-demand and uses [actions/runner][5] to start a runner.\n\n| | EC2 | CodeBuild | Fargate | ECS | Lambda |\n|------------------|-------------------|----------------------------|----------------|----------------|---------------|\n| **Time limit** | Unlimited | 8 hours | Unlimited | Unlimited | 15 minutes |\n| **vCPUs** | Unlimited | 2, 4, 8, or 72 | 0.25 to 4 | Unlimited | 1 to 6 |\n| **RAM** | Unlimited | 3gb, 7gb, 15gb, or 145gb | 512mb to 30gb | Unlimited | 128mb to 10gb |\n| **Storage** | Unlimited | 50gb to 824gb | 20gb to 200gb | Unlimited | Up to 10gb |\n| **Architecture** | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 | x86_64, ARM64 |\n| **sudo** | ✔ | ✔ | ✔ | ✔ | ❌ |\n| **Docker** | ✔ | ✔ (Linux only) | ❌ | ✔ | ❌ |\n| **Spot pricing** | ✔ | ❌ | ✔ | ✔ | ❌ |\n| **OS** | Linux, Windows | Linux, Windows | Linux, Windows | Linux, Windows | Linux |\n\nThe best provider to use mostly depends on your current infrastructure. When in doubt, CodeBuild is always a good choice. Execution history and logs are easy to view, and it has no restrictive limits unless you need to run for more than 8 hours.\n\n* EC2 is useful when you want runners to have complete access to the host\n* ECS is useful when you want to control the infrastructure, like leaving the runner host running for faster startups\n* Lambda is useful for short jobs that can work within time, size and readonly system constraints\n\nYou can also create your own provider by implementing `IRunnerProvider`.\n\n## Installation\n\n1. Install and use the appropriate package\n <details><summary>Python</summary>\n\n ### Install\n Available on [PyPI][6].\n ```bash\n pip install cloudsnorkel.cdk-github-runners\n ```\n ### Use\n ```python\n from cloudsnorkel.cdk_github_runners import GitHubRunners\n\n GitHubRunners(self, \"runners\")\n ```\n </details>\n <details><summary>TypeScript or JavaScript</summary>\n\n ### Install\n Available on [npm][7].\n ```bash\n npm i @cloudsnorkel/cdk-github-runners\n ```\n ### Use\n ```typescript\n import { GitHubRunners } from '@cloudsnorkel/cdk-github-runners';\n\n new GitHubRunners(this, \"runners\");\n ```\n </details>\n <details><summary>Java</summary>\n\n ### Install\n Available on [Maven][8].\n ```xml\n <dependency>\n <groupId>com.cloudsnorkel</groupId>\n <artifactId>cdk.github.runners</artifactId>\n </dependency>\n ```\n ### Use\n ```java\n import com.cloudsnorkel.cdk.github.runners.GitHubRunners;\n\n GitHubRunners.Builder.create(this, \"runners\").build();\n ```\n </details>\n <details><summary>Go</summary>\n\n ### Install\n Available on [GitHub][11].\n ```bash\n go get github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n ```\n ### Use\n ```go\n import \"github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\"\n\n NewGitHubRunners(this, jsii.String(\"runners\"))\n ```\n </details>\n <details><summary>.NET</summary>\n\n ### Install\n Available on [Nuget][12].\n ```bash\n dotnet add package CloudSnorkel.Cdk.Github.Runners\n ```\n ### Use\n ```csharp\n using CloudSnorkel;\n\n new GitHubRunners(this, \"runners\");\n ```\n </details>\n2. Use `GitHubRunners` construct in your code (starting with default arguments is fine)\n3. Deploy your stack\n4. Look for the status command output similar to `aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json`\n ```\n ✅ github-runners-test\n\n ✨ Deployment time: 260.01s\n\n Outputs:\n github-runners-test.runnersstatuscommand4A30F0F5 = aws --region us-east-1 lambda invoke --function-name github-runners-test-runnersstatus1A5771C0-mvttg8oPQnQS status.json\n ```\n5. Execute the status command (you may need to specify `--profile` too) and open the resulting `status.json` file\n6. Open the URL in `github.setup.url` from `status.json` or [manually setup GitHub](SETUP_GITHUB.md) integration as an app or with personal access token\n7. Run status command again to confirm `github.auth.status` and `github.webhook.status` are OK\n8. Trigger a GitHub action that has a `self-hosted` label with `runs-on: [self-hosted, linux, codebuild]` or similar\n9. If the action is not successful, see [troubleshooting](#Troubleshooting)\n\n[![Demo](demo-thumbnail.jpg)](https://youtu.be/wlyv_3V8lIw)\n\n## Customizing\n\nThe default providers configured by `GitHubRunners` are useful for testing but probably not too much for actual production work. They run in the default VPC or no VPC and have no added IAM permissions. You would usually want to configure the providers yourself.\n\nFor example:\n\n```typescript\nlet vpc: ec2.Vpc;\nlet runnerSg: ec2.SecurityGroup;\nlet dbSg: ec2.SecurityGroup;\nlet bucket: s3.Bucket;\n\n// create a custom CodeBuild provider\nconst myProvider = new CodeBuildRunnerProvider(this, 'codebuild runner', {\n labels: ['my-codebuild'],\n vpc: vpc,\n securityGroups: [runnerSg],\n});\n// grant some permissions to the provider\nbucket.grantReadWrite(myProvider);\ndbSg.connections.allowFrom(runnerSg, ec2.Port.tcp(3306), 'allow runners to connect to MySQL database');\n\n// create the runner infrastructure\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nAnother way to customize runners is by modifying the image used to spin them up. The image contains the [runner][5], any required dependencies, and integration code with the provider. You may choose to customize this image by adding more packages, for example.\n\n```typescript\nconst myBuilder = CodeBuildRunnerProvider.imageBuilder(this, 'image builder', {\n dockerfilePath: FargateRunner.LINUX_X64_DOCKERFILE_PATH,\n runnerVersion: RunnerVersion.specific('2.291.0'),\n rebuildInterval: Duration.days(14),\n});\nmyBuilder.addComponent(\n RunnerImageComponent.custom({ commands: ['apt install -y nginx xz-utils'] })\n);\n\nconst myProvider = new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['customized-fargate'],\n vpc: vpc,\n securityGroups: [runnerSg],\n imageBuilder: myBuilder,\n});\n\n// create the runner infrastructure\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nYour workflow will then look like:\n\n```yaml\nname: self-hosted example\non: push\njobs:\n self-hosted:\n runs-on: [self-hosted, customized-fargate]\n steps:\n - run: echo hello world\n```\n\nWindows images can also be customized the same way.\n\n```typescript\nconst myWindowsBuilder = FargateRunnerProvider.imageBuilder(this, 'Windows image builder', {\n architecture: Architecture.X86_64,\n os: Os.WINDOWS,\n runnerVersion: RunnerVersion.specific('2.291.0'),\n rebuildInterval: Duration.days(14),\n});\nmyWindowsBuilder.addComponent(\n RunnerImageComponent.custom({\n name: 'Ninja',\n commands: [\n 'Invoke-WebRequest -UseBasicParsing -Uri \"https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip\" -OutFile ninja.zip',\n 'Expand-Archive ninja.zip -DestinationPath C:\\\\actions',\n 'del ninja.zip',\n ],\n })\n);\n\nconst myProvider = new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['customized-windows-fargate'],\n vpc: vpc,\n securityGroups: [runnerSg],\n imageBuilder: myWindowsBuilder,\n});\n\nnew GitHubRunners(this, 'runners', {\n providers: [myProvider],\n});\n```\n\nThe runner OS and architecture is determined by the image it is set to use. For example, to create a Fargate runner provider for ARM64 set the `architecture` property for the image builder to `Architecture.ARM64` in the image builder properties.\n\n```typescript\nnew GitHubRunners(this, 'runners', {\n providers: [\n new FargateRunnerProvider(this, 'fargate runner', {\n labels: ['arm64', 'fargate'],\n imageBuilder: FargateRunnerProvider.imageBuilder(this, 'image builder', {\n architecture: Architecture.ARM64,\n os: Os.LINUX_UBUNTU,\n }),\n }),\n ],\n});\n```\n\n## Architecture\n\n![Architecture diagram](architecture.svg)\n\n## Troubleshooting\n\nRunners are started in response to a webhook coming in from GitHub. If there are any issues starting the runner like missing capacity or transient API issues, the provider will keep retrying for 24 hours. Configuration issue related errors like pointing to a missing AMI will not be retried. GitHub itself will cancel the job if it can't find a runner for 24 hours. If your jobs don't start, follow the steps below to examine all parts of this workflow.\n\n1. Always start with the status function, make sure no errors are reported, and confirm all status codes are OK\n2. Make sure `runs-on` in the workflow matches the expected labels set in the runner provider\n3. Diagnose relevant executions of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`\n 1. If the execution failed, check your runner provider configuration for errors\n 2. If the execution is still running for a long time, check the execution events to see why runner starting is being retried\n 3. If there are no relevant executions, move to the next step\n4. Confirm the webhook Lambda was called by visiting the URL in `troubleshooting.webhookHandlerUrl` from `status.json`\n 1. If it's not called or logs errors, confirm the webhook settings on the GitHub side\n 2. If you see too many errors, make sure you're only sending `workflow_job` events\n5. When using GitHub app, make sure there are active installations in `github.auth.app.installations`\n\nAll logs are saved in CloudWatch.\n* Log group names can be found in `status.json` for each provider, image builder, and other parts of the system\n* Some useful Logs Insights queries can be enabled with `GitHubRunners.createLogsInsightsQueries()`\n\nTo get `status.json`, check out the CloudFormation stack output for a command that generates it. The command looks like:\n\n```\naws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json\n```\n\n## Monitoring\n\nThere are two important ways to monitor your runners:\n\n1. Make sure runners don't fail to start. When that happens, jobs may sit and wait. Use `GitHubRunners.metricFailed()` to get a metric for the number of failed runner starts. You should use this metric to trigger an alarm.\n2. Make sure runner images don't fail to build. Failed runner image builds mean you will get stuck with out-of-date software on your runners. It may lead to security vulnerabilities, or it may lead to slower runner start-ups as the runner software itself needs to be updated. Use `GitHubRunners.failedImageBuildsTopic()` to get SNS topic that gets notified of failed runner image builds. You should subscribe to this topic.\n\nOther useful metrics to track:\n\n1. Use `GitHubRunners.metricJobCompleted()` to get a metric for the number of completed jobs broken down by labels and job success.\n2. Use `GitHubRunners.metricTime()` to get a metric for the total time a runner is running. This includes the overhead of starting the runner.\n\n## Other Options\n\n1. [philips-labs/terraform-aws-github-runner][3] if you're using Terraform\n2. [actions/actions-runner-controller][4] if you're using Kubernetes\n\n\n[1]: https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners\n[2]: https://github.com/marketplace/actions/configure-aws-credentials-for-github-actions\n[3]: https://github.com/philips-labs/terraform-aws-github-runner\n[4]: https://github.com/actions/actions-runner-controller\n[5]: https://github.com/actions/runner\n[6]: https://pypi.org/project/cloudsnorkel.cdk-github-runners\n[7]: https://www.npmjs.com/package/@cloudsnorkel/cdk-github-runners\n[8]: https://central.sonatype.com/artifact/com.cloudsnorkel/cdk.github.runners/\n[9]: https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps\n[10]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token\n[11]: https://pkg.go.dev/github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n[12]: https://www.nuget.org/packages/CloudSnorkel.Cdk.Github.Runners/\n[13]: https://constructs.dev/packages/@cloudsnorkel/cdk-github-runners/\n[14]: https://docs.github.com/en/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#using-ephemeral-runners-for-autoscaling\n"
3441
3441
  },
3442
3442
  "repository": {
3443
3443
  "type": "git",
@@ -8427,6 +8427,18 @@
8427
8427
  "line": 234
8428
8428
  },
8429
8429
  "methods": [
8430
+ {
8431
+ "docs": {
8432
+ "remarks": "* \"Webhook errors\" helps diagnose configuration issues with GitHub integration\n* \"Ignored webhook\" helps understand why runners aren't started\n* \"Ignored jobs based on labels\" helps debug label matching issues\n* \"Webhook started runners\" helps understand which runners were started",
8433
+ "stability": "experimental",
8434
+ "summary": "Creates CloudWatch Logs Insights saved queries that can be used to debug issues with the runners."
8435
+ },
8436
+ "locationInModule": {
8437
+ "filename": "src/runner.ts",
8438
+ "line": 766
8439
+ },
8440
+ "name": "createLogsInsightsQueries"
8441
+ },
8430
8442
  {
8431
8443
  "docs": {
8432
8444
  "remarks": "Runner images are rebuilt every week by default. This provides the latest GitHub Runner version and software updates.\n\nIf you want to be sure you are using the latest runner version, you can use this topic to be notified when a build fails.",
@@ -9906,7 +9918,7 @@
9906
9918
  },
9907
9919
  "locationInModule": {
9908
9920
  "filename": "src/providers/lambda.ts",
9909
- "line": 224
9921
+ "line": 229
9910
9922
  },
9911
9923
  "parameters": [
9912
9924
  {
@@ -9933,7 +9945,7 @@
9933
9945
  "kind": "class",
9934
9946
  "locationInModule": {
9935
9947
  "filename": "src/providers/lambda.ts",
9936
- "line": 456
9948
+ "line": 461
9937
9949
  },
9938
9950
  "name": "LambdaRunner",
9939
9951
  "symbolId": "src/providers/lambda:LambdaRunner"
@@ -9953,7 +9965,7 @@
9953
9965
  },
9954
9966
  "locationInModule": {
9955
9967
  "filename": "src/providers/lambda.ts",
9956
- "line": 224
9968
+ "line": 229
9957
9969
  },
9958
9970
  "parameters": [
9959
9971
  {
@@ -9988,7 +10000,7 @@
9988
10000
  "methods": [
9989
10001
  {
9990
10002
  "docs": {
9991
- "remarks": "Included components:\n * `RunnerImageComponent.requiredPackages()`\n * `RunnerImageComponent.runnerUser()`\n * `RunnerImageComponent.git()`\n * `RunnerImageComponent.githubCli()`\n * `RunnerImageComponent.awsCli()`\n * `RunnerImageComponent.githubRunner()`\n * `RunnerImageComponent.lambdaEntrypoint()`\n\n Base Docker image: `public.ecr.aws/lambda/nodejs:14-x86_64` or `public.ecr.aws/lambda/nodejs:14-arm64`",
10003
+ "remarks": "Included components:\n * `RunnerImageComponent.requiredPackages()`\n * `RunnerImageComponent.runnerUser()`\n * `RunnerImageComponent.git()`\n * `RunnerImageComponent.githubCli()`\n * `RunnerImageComponent.awsCli()`\n * `RunnerImageComponent.githubRunner()`\n * `RunnerImageComponent.lambdaEntrypoint()`\n\n Base Docker image: `public.ecr.aws/lambda/nodejs:16-x86_64` or `public.ecr.aws/lambda/nodejs:16-arm64`",
9992
10004
  "stability": "experimental",
9993
10005
  "summary": "Create new image builder that builds Lambda specific runner images using Amazon Linux 2."
9994
10006
  },
@@ -10033,7 +10045,7 @@
10033
10045
  },
10034
10046
  "locationInModule": {
10035
10047
  "filename": "src/providers/lambda.ts",
10036
- "line": 312
10048
+ "line": 317
10037
10049
  },
10038
10050
  "name": "getStepFunctionTask",
10039
10051
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -10062,7 +10074,7 @@
10062
10074
  },
10063
10075
  "locationInModule": {
10064
10076
  "filename": "src/providers/lambda.ts",
10065
- "line": 373
10077
+ "line": 378
10066
10078
  },
10067
10079
  "name": "grantStateMachine",
10068
10080
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -10131,7 +10143,7 @@
10131
10143
  },
10132
10144
  "locationInModule": {
10133
10145
  "filename": "src/providers/lambda.ts",
10134
- "line": 376
10146
+ "line": 381
10135
10147
  },
10136
10148
  "name": "status",
10137
10149
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -10198,7 +10210,7 @@
10198
10210
  "immutable": true,
10199
10211
  "locationInModule": {
10200
10212
  "filename": "src/providers/lambda.ts",
10201
- "line": 301
10213
+ "line": 306
10202
10214
  },
10203
10215
  "name": "connections",
10204
10216
  "overrides": "aws-cdk-lib.aws_ec2.IConnectable",
@@ -10214,7 +10226,7 @@
10214
10226
  "immutable": true,
10215
10227
  "locationInModule": {
10216
10228
  "filename": "src/providers/lambda.ts",
10217
- "line": 189
10229
+ "line": 194
10218
10230
  },
10219
10231
  "name": "function",
10220
10232
  "type": {
@@ -10229,7 +10241,7 @@
10229
10241
  "immutable": true,
10230
10242
  "locationInModule": {
10231
10243
  "filename": "src/providers/lambda.ts",
10232
- "line": 199
10244
+ "line": 204
10233
10245
  },
10234
10246
  "name": "grantPrincipal",
10235
10247
  "overrides": "aws-cdk-lib.aws_iam.IGrantable",
@@ -10246,7 +10258,7 @@
10246
10258
  "immutable": true,
10247
10259
  "locationInModule": {
10248
10260
  "filename": "src/providers/lambda.ts",
10249
- "line": 204
10261
+ "line": 209
10250
10262
  },
10251
10263
  "name": "image",
10252
10264
  "type": {
@@ -10261,7 +10273,7 @@
10261
10273
  "immutable": true,
10262
10274
  "locationInModule": {
10263
10275
  "filename": "src/providers/lambda.ts",
10264
- "line": 194
10276
+ "line": 199
10265
10277
  },
10266
10278
  "name": "labels",
10267
10279
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -10283,7 +10295,7 @@
10283
10295
  "immutable": true,
10284
10296
  "locationInModule": {
10285
10297
  "filename": "src/providers/lambda.ts",
10286
- "line": 211
10298
+ "line": 216
10287
10299
  },
10288
10300
  "name": "logGroup",
10289
10301
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -10299,7 +10311,7 @@
10299
10311
  "immutable": true,
10300
10312
  "locationInModule": {
10301
10313
  "filename": "src/providers/lambda.ts",
10302
- "line": 213
10314
+ "line": 218
10303
10315
  },
10304
10316
  "name": "retryableErrors",
10305
10317
  "overrides": "@cloudsnorkel/cdk-github-runners.IRunnerProvider",
@@ -13312,6 +13324,6 @@
13312
13324
  "symbolId": "src/image-builders/aws-image-builder/deprecated/windows-components:WindowsComponents"
13313
13325
  }
13314
13326
  },
13315
- "version": "0.11.0",
13316
- "fingerprint": "gKSzhOGxVfhAyFxTjEhWZdtH7yFsN3G1L6jcxzVAiZc="
13327
+ "version": "0.11.1",
13328
+ "fingerprint": "mTC5uTa9W4WUsRC7U4/9pMkGsZF1IjnX7GFhUnpMLgM="
13317
13329
  }
package/API.md CHANGED
@@ -3199,6 +3199,7 @@ new GitHubRunners(scope: Construct, id: string, props?: GitHubRunnersProps)
3199
3199
  | **Name** | **Description** |
3200
3200
  | --- | --- |
3201
3201
  | <code><a href="#@cloudsnorkel/cdk-github-runners.GitHubRunners.toString">toString</a></code> | Returns a string representation of this construct. |
3202
+ | <code><a href="#@cloudsnorkel/cdk-github-runners.GitHubRunners.createLogsInsightsQueries">createLogsInsightsQueries</a></code> | Creates CloudWatch Logs Insights saved queries that can be used to debug issues with the runners. |
3202
3203
  | <code><a href="#@cloudsnorkel/cdk-github-runners.GitHubRunners.failedImageBuildsTopic">failedImageBuildsTopic</a></code> | Creates a topic for notifications when a runner image build fails. |
3203
3204
  | <code><a href="#@cloudsnorkel/cdk-github-runners.GitHubRunners.metricFailed">metricFailed</a></code> | Metric for failed runner executions. |
3204
3205
  | <code><a href="#@cloudsnorkel/cdk-github-runners.GitHubRunners.metricJobCompleted">metricJobCompleted</a></code> | Metric for the number of GitHub Actions jobs completed. |
@@ -3215,6 +3216,19 @@ public toString(): string
3215
3216
 
3216
3217
  Returns a string representation of this construct.
3217
3218
 
3219
+ ##### `createLogsInsightsQueries` <a name="createLogsInsightsQueries" id="@cloudsnorkel/cdk-github-runners.GitHubRunners.createLogsInsightsQueries"></a>
3220
+
3221
+ ```typescript
3222
+ public createLogsInsightsQueries(): void
3223
+ ```
3224
+
3225
+ Creates CloudWatch Logs Insights saved queries that can be used to debug issues with the runners.
3226
+
3227
+ * "Webhook errors" helps diagnose configuration issues with GitHub integration
3228
+ * "Ignored webhook" helps understand why runners aren't started
3229
+ * "Ignored jobs based on labels" helps debug label matching issues
3230
+ * "Webhook started runners" helps understand which runners were started
3231
+
3218
3232
  ##### `failedImageBuildsTopic` <a name="failedImageBuildsTopic" id="@cloudsnorkel/cdk-github-runners.GitHubRunners.failedImageBuildsTopic"></a>
3219
3233
 
3220
3234
  ```typescript
@@ -3825,7 +3839,7 @@ Included components:
3825
3839
  * `RunnerImageComponent.githubRunner()`
3826
3840
  * `RunnerImageComponent.lambdaEntrypoint()`
3827
3841
 
3828
- Base Docker image: `public.ecr.aws/lambda/nodejs:14-x86_64` or `public.ecr.aws/lambda/nodejs:14-arm64`
3842
+ Base Docker image: `public.ecr.aws/lambda/nodejs:16-x86_64` or `public.ecr.aws/lambda/nodejs:16-arm64`
3829
3843
 
3830
3844
  ###### `scope`<sup>Required</sup> <a name="scope" id="@cloudsnorkel/cdk-github-runners.LambdaRunner.imageBuilder.parameter.scope"></a>
3831
3845
 
@@ -4185,7 +4199,7 @@ Included components:
4185
4199
  * `RunnerImageComponent.githubRunner()`
4186
4200
  * `RunnerImageComponent.lambdaEntrypoint()`
4187
4201
 
4188
- Base Docker image: `public.ecr.aws/lambda/nodejs:14-x86_64` or `public.ecr.aws/lambda/nodejs:14-arm64`
4202
+ Base Docker image: `public.ecr.aws/lambda/nodejs:16-x86_64` or `public.ecr.aws/lambda/nodejs:16-arm64`
4189
4203
 
4190
4204
  ###### `scope`<sup>Required</sup> <a name="scope" id="@cloudsnorkel/cdk-github-runners.LambdaRunnerProvider.imageBuilder.parameter.scope"></a>
4191
4205
 
package/README.md CHANGED
@@ -280,6 +280,16 @@ Runners are started in response to a webhook coming in from GitHub. If there are
280
280
  2. If you see too many errors, make sure you're only sending `workflow_job` events
281
281
  5. When using GitHub app, make sure there are active installations in `github.auth.app.installations`
282
282
 
283
+ All logs are saved in CloudWatch.
284
+ * Log group names can be found in `status.json` for each provider, image builder, and other parts of the system
285
+ * Some useful Logs Insights queries can be enabled with `GitHubRunners.createLogsInsightsQueries()`
286
+
287
+ To get `status.json`, check out the CloudFormation stack output for a command that generates it. The command looks like:
288
+
289
+ ```
290
+ aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json
291
+ ```
292
+
283
293
  ## Monitoring
284
294
 
285
295
  There are two important ways to monitor your runners:
@@ -15105,6 +15105,11 @@ function lambdaArnToUrl(arn) {
15105
15105
  const name = parts[6];
15106
15106
  return `https://${region}.console.aws.amazon.com/lambda/home?region=${region}#/functions/${name}?tab=monitoring`;
15107
15107
  }
15108
+ function lambdaArnToLogGroup(arn) {
15109
+ const parts = arn.split(":");
15110
+ const name = parts[6];
15111
+ return `/aws/lambda/${name}`;
15112
+ }
15108
15113
  function stepFunctionArnToUrl(arn) {
15109
15114
  const parts = arn.split(":");
15110
15115
  const region = parts[3];
@@ -15197,6 +15202,7 @@ async function handler(event) {
15197
15202
  troubleshooting: {
15198
15203
  webhookHandlerArn: process.env.WEBHOOK_HANDLER_ARN,
15199
15204
  webhookHandlerUrl: lambdaArnToUrl(process.env.WEBHOOK_HANDLER_ARN),
15205
+ webhookHandlerLogGroup: lambdaArnToLogGroup(process.env.WEBHOOK_HANDLER_ARN),
15200
15206
  stepFunctionArn: process.env.STEP_FUNCTION_ARN,
15201
15207
  stepFunctionUrl: stepFunctionArnToUrl(process.env.STEP_FUNCTION_ARN),
15202
15208
  stepFunctionLogGroup: process.env.STEP_FUNCTION_LOG_GROUP,