@cloudsnorkel/cdk-github-runners 0.0.13 → 0.1.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
@@ -2995,7 +2995,7 @@
2995
2995
  },
2996
2996
  "name": "@cloudsnorkel/cdk-github-runners",
2997
2997
  "readme": {
2998
- "markdown": "# GitHub Self-Hosted Runners CDK Constructs\n\n[![NPM](https://img.shields.io/npm/v/@cloudsnorkel/cdk-github-runners?label=npm&logo=npm)][6]\n[![PyPI](https://img.shields.io/pypi/v/cloudsnorkel.cdk-github-runners?label=pypi&logo=pypi)][7]\n[![Maven Central](https://img.shields.io/maven-central/v/com.cloudsnorkel/cdk.github.runners.svg?label=Maven%20Central&logo=java)][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\n* Customizable runners with decent defaults\n* Supports multiple runner configurations controlled by labels\n* Everything fully hosted in your account\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 ([aws-actions/configure-aws-credentials][2] has more security controls)\n\nEphemeral 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\nDocumentation of available constructs and their interface is available on [Constructs Hub][13] 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| Provider | Time limit | vCPUs | RAM | Storage | sudo | Docker |\n|-----------|--------------------------|--------------------------|-----------------------------------|------------------------------|------|--------|\n| CodeBuild | 8 hours (default 1 hour) | 2 (default), 4, 8, or 72 | 3gb (default), 7gb, 15gb or 145gb | 50gb to 824gb (default 64gb) | ✔ | ✔ |\n| Fargate | Unlimited | 0.25 to 4 (default 1) | 512mb to 30gb (default 2gb) | 20gb to 200gb (default 25gb) | ✔ | ❌ |\n| Lambda | 15 minutes | 1 to 6 (default 2) | 128mb to 10gb (default 2gb) | Up to 10gb (default 10gb) | ❌ | ❌ |\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\nYou can also create your own provider by implementing `IRunnerProvider`.\n\n## Installation\n\n1. Confirm you're using CDK v2\n2. Install the appropriate package\n 1. [Python][6]\n ```\n pip install cloudsnorkel.cdk-github-runners\n ```\n 2. [TypeScript or JavaScript][7]\n ```\n npm i @cloudsnorkel/cdk-github-runners\n ```\n 3. [Java][8]\n ```xml\n <dependency>\n <groupId>com.cloudsnorkel</groupId>\n <artifactId>cdk.github.runners</artifactId>\n </dependency>\n ```\n 4. [Go][11]\n ```\n go get github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n ```\n 5. [.NET][12]\n ```\n dotnet add package CloudSnorkel.Cdk.Github.Runners\n ```\n3. Use `GitHubRunners` construct in your code (starting with default arguments is fine)\n4. Deploy your stack\n5. Look for the status command output similar to `aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json`\n6. Execute the status command (you may need to specify `--profile` too) and open the resulting `status.json` file\n7. [Setup GitHub](SETUP_GITHUB.md) integration as an app or with personal access token\n8. Run status command again to confirm `github.auth.status` and `github.webhook.status` are OK\n9. Trigger a GitHub action that has a `self-hosted` label with `runs-on: [self-hosted, linux, codebuild]` or similar\n10. If the action is not successful, see [troubleshooting](#Troubleshooting)\n\n## Customizing\n\nThe default providers configured by [`GitHubRunners`](https://constructs.dev/packages/@cloudsnorkel/cdk-github-runners/v/0.0.11/api/GitHubRunners?lang=typescript) 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\nimport * as cdk from 'aws-cdk-lib';\nimport { aws_ec2 as ec2, aws_s3 as s3 } from 'aws-cdk-lib';\nimport { GitHubRunners, CodeBuildRunner } from '@cloudsnorkel/cdk-github-runners';\n\nconst app = new cdk.App();\nconst stack = new cdk.Stack(\n app,\n 'github-runners-test',\n {\n env: {\n account: process.env.CDK_DEFAULT_ACCOUNT,\n region: process.env.CDK_DEFAULT_REGION,\n },\n },\n);\n\nconst vpc = ec2.Vpc.fromLookup(stack, 'vpc', { vpcId: 'vpc-1234567' });\nconst runnerSg = new ec2.SecurityGroup(stack, 'runner security group', { vpc: vpc });\nconst dbSg = ec2.SecurityGroup.fromSecurityGroupId(stack, 'database security group', 'sg-1234567');\nconst bucket = new s3.Bucket(stack, 'runner bucket');\n\n// create a custom CodeBuild provider\nconst myProvider = new CodeBuildRunner(\n stack, 'codebuild runner',\n {\n label: 'my-codebuild',\n vpc: vpc,\n securityGroup: runnerSg,\n },\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(\n stack,\n 'runners',\n {\n providers: [myProvider],\n defaultProviderLabel: 'my-codebuild',\n }\n);\n\napp.synth();\n```\n\n## Architecture\n\n![Architecture diagram](architecture.svg)\n\n## Troubleshooting\n\n1. Always start with the status function, make sure no errors are reported, and confirm all status codes are OK\n2. 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\n3. Check execution details of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`\n 1. Use the details tab to find the specific execution of the provider (Lambda, CodeBuild, Fargate, etc.)\n 2. Every step function execution should be successful, even if the runner action inside it failed\n\n## Other Options\n\n1. [philips-labs/terraform-aws-github-runner][3] if you're using Terraform\n2. [actions-runner-controller/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-action-for-github-actions\n[3]: https://github.com/philips-labs/terraform-aws-github-runner\n[4]: https://github.com/actions-runner-controller/actions-runner-controller\n[5]: https://github.com/actions/runner\n[6]: https://www.npmjs.com/package/@cloudsnorkel/cdk-github-runners\n[7]: https://pypi.org/project/cloudsnorkel.cdk-github-runners\n[8]: https://search.maven.org/search?q=g:%22com.cloudsnorkel%22%20AND%20a:%22cdk.github.runners%22\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"
2998
+ "markdown": "# GitHub Self-Hosted Runners CDK Constructs\n\n[![NPM](https://img.shields.io/npm/v/@cloudsnorkel/cdk-github-runners?label=npm&logo=npm)][6]\n[![PyPI](https://img.shields.io/pypi/v/cloudsnorkel.cdk-github-runners?label=pypi&logo=pypi)][7]\n[![Maven Central](https://img.shields.io/maven-central/v/com.cloudsnorkel/cdk.github.runners.svg?label=Maven%20Central&logo=java)][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\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\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| Provider | Time limit | vCPUs | RAM | Storage | sudo | Docker |\n|-----------|--------------------------|--------------------------|-----------------------------------|------------------------------|------|--------|\n| CodeBuild | 8 hours (default 1 hour) | 2 (default), 4, 8, or 72 | 3gb (default), 7gb, 15gb or 145gb | 50gb to 824gb (default 64gb) | ✔ | ✔ |\n| Fargate | Unlimited | 0.25 to 4 (default 1) | 512mb to 30gb (default 2gb) | 20gb to 200gb (default 25gb) | ✔ | ❌ |\n| Lambda | 15 minutes | 1 to 6 (default 2) | 128mb to 10gb (default 2gb) | Up to 10gb (default 10gb) | ❌ | ❌ |\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\nYou can also create your own provider by implementing `IRunnerProvider`.\n\n## Installation\n\n1. Confirm you're using CDK v2\n2. Install the appropriate package\n 1. [Python][6]\n ```\n pip install cloudsnorkel.cdk-github-runners\n ```\n 2. [TypeScript or JavaScript][7]\n ```\n npm i @cloudsnorkel/cdk-github-runners\n ```\n 3. [Java][8]\n ```xml\n <dependency>\n <groupId>com.cloudsnorkel</groupId>\n <artifactId>cdk.github.runners</artifactId>\n </dependency>\n ```\n 4. [Go][11]\n ```\n go get github.com/CloudSnorkel/cdk-github-runners-go/cloudsnorkelcdkgithubrunners\n ```\n 5. [.NET][12]\n ```\n dotnet add package CloudSnorkel.Cdk.Github.Runners\n ```\n3. Use `GitHubRunners` construct in your code (starting with default arguments is fine)\n4. Deploy your stack\n5. Look for the status command output similar to `aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json`\n6. Execute the status command (you may need to specify `--profile` too) and open the resulting `status.json` file\n7. 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\n8. Run status command again to confirm `github.auth.status` and `github.webhook.status` are OK\n9. Trigger a GitHub action that has a `self-hosted` label with `runs-on: [self-hosted, linux, codebuild]` or similar\n10. If the action is not successful, see [troubleshooting](#Troubleshooting)\n\n## Customizing\n\nThe default providers configured by [`GitHubRunners`](https://constructs.dev/packages/@cloudsnorkel/cdk-github-runners/v/0.0.11/api/GitHubRunners?lang=typescript) 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\nimport * as cdk from 'aws-cdk-lib';\nimport { aws_ec2 as ec2, aws_s3 as s3 } from 'aws-cdk-lib';\nimport { GitHubRunners, CodeBuildRunner } from '@cloudsnorkel/cdk-github-runners';\n\nconst app = new cdk.App();\nconst stack = new cdk.Stack(\n app,\n 'github-runners-test',\n {\n env: {\n account: process.env.CDK_DEFAULT_ACCOUNT,\n region: process.env.CDK_DEFAULT_REGION,\n },\n },\n);\n\nconst vpc = ec2.Vpc.fromLookup(stack, 'vpc', { vpcId: 'vpc-1234567' });\nconst runnerSg = new ec2.SecurityGroup(stack, 'runner security group', { vpc: vpc });\nconst dbSg = ec2.SecurityGroup.fromSecurityGroupId(stack, 'database security group', 'sg-1234567');\nconst bucket = new s3.Bucket(stack, 'runner bucket');\n\n// create a custom CodeBuild provider\nconst myProvider = new CodeBuildRunner(\n stack, 'codebuild runner',\n {\n label: 'my-codebuild',\n vpc: vpc,\n securityGroup: runnerSg,\n },\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(\n stack,\n 'runners',\n {\n providers: [myProvider],\n defaultProviderLabel: 'my-codebuild',\n }\n);\n\napp.synth();\n```\n\n## Architecture\n\n![Architecture diagram](architecture.svg)\n\n## Troubleshooting\n\n1. Always start with the status function, make sure no errors are reported, and confirm all status codes are OK\n2. 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\n3. When using GitHub app, make sure there are active installation in `github.auth.app.installations`\n4. Check execution details of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`\n 1. Use the details tab to find the specific execution of the provider (Lambda, CodeBuild, Fargate, etc.)\n 2. Every step function execution should be successful, even if the runner action inside it failed\n\n## Other Options\n\n1. [philips-labs/terraform-aws-github-runner][3] if you're using Terraform\n2. [actions-runner-controller/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-action-for-github-actions\n[3]: https://github.com/philips-labs/terraform-aws-github-runner\n[4]: https://github.com/actions-runner-controller/actions-runner-controller\n[5]: https://github.com/actions/runner\n[6]: https://www.npmjs.com/package/@cloudsnorkel/cdk-github-runners\n[7]: https://pypi.org/project/cloudsnorkel.cdk-github-runners\n[8]: https://search.maven.org/search?q=g:%22com.cloudsnorkel%22%20AND%20a:%22cdk.github.runners%22\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"
2999
2999
  },
3000
3000
  "repository": {
3001
3001
  "type": "git",
@@ -3743,7 +3743,7 @@
3743
3743
  },
3744
3744
  "locationInModule": {
3745
3745
  "filename": "src/runner.ts",
3746
- "line": 93
3746
+ "line": 95
3747
3747
  },
3748
3748
  "parameters": [
3749
3749
  {
@@ -3769,7 +3769,7 @@
3769
3769
  "kind": "class",
3770
3770
  "locationInModule": {
3771
3771
  "filename": "src/runner.ts",
3772
- "line": 73
3772
+ "line": 74
3773
3773
  },
3774
3774
  "name": "GitHubRunners",
3775
3775
  "properties": [
@@ -3781,7 +3781,7 @@
3781
3781
  "immutable": true,
3782
3782
  "locationInModule": {
3783
3783
  "filename": "src/runner.ts",
3784
- "line": 83
3784
+ "line": 84
3785
3785
  },
3786
3786
  "name": "defaultProvider",
3787
3787
  "type": {
@@ -3795,7 +3795,7 @@
3795
3795
  "immutable": true,
3796
3796
  "locationInModule": {
3797
3797
  "filename": "src/runner.ts",
3798
- "line": 93
3798
+ "line": 95
3799
3799
  },
3800
3800
  "name": "props",
3801
3801
  "type": {
@@ -3810,7 +3810,7 @@
3810
3810
  "immutable": true,
3811
3811
  "locationInModule": {
3812
3812
  "filename": "src/runner.ts",
3813
- "line": 78
3813
+ "line": 79
3814
3814
  },
3815
3815
  "name": "providers",
3816
3816
  "type": {
@@ -3830,7 +3830,7 @@
3830
3830
  "immutable": true,
3831
3831
  "locationInModule": {
3832
3832
  "filename": "src/runner.ts",
3833
- "line": 88
3833
+ "line": 89
3834
3834
  },
3835
3835
  "name": "secrets",
3836
3836
  "type": {
@@ -3851,7 +3851,7 @@
3851
3851
  "kind": "interface",
3852
3852
  "locationInModule": {
3853
3853
  "filename": "src/runner.ts",
3854
- "line": 15
3854
+ "line": 16
3855
3855
  },
3856
3856
  "name": "GitHubRunnersProps",
3857
3857
  "properties": [
@@ -3866,7 +3866,7 @@
3866
3866
  "immutable": true,
3867
3867
  "locationInModule": {
3868
3868
  "filename": "src/runner.ts",
3869
- "line": 22
3869
+ "line": 23
3870
3870
  },
3871
3871
  "name": "defaultProviderLabel",
3872
3872
  "optional": true,
@@ -3885,7 +3885,7 @@
3885
3885
  "immutable": true,
3886
3886
  "locationInModule": {
3887
3887
  "filename": "src/runner.ts",
3888
- "line": 29
3888
+ "line": 30
3889
3889
  },
3890
3890
  "name": "providers",
3891
3891
  "optional": true,
@@ -4598,7 +4598,7 @@
4598
4598
  },
4599
4599
  "locationInModule": {
4600
4600
  "filename": "src/secrets.ts",
4601
- "line": 29
4601
+ "line": 34
4602
4602
  },
4603
4603
  "parameters": [
4604
4604
  {
@@ -4640,7 +4640,7 @@
4640
4640
  },
4641
4641
  {
4642
4642
  "docs": {
4643
- "remarks": "This secret is meant to be edited by the user after being created.",
4643
+ "remarks": "This secret is meant to be edited by the user after being created. It is separate than the main GitHub secret because inserting private keys into JSON is hard.",
4644
4644
  "stability": "experimental",
4645
4645
  "summary": "GitHub app private key. Not needed when using personal authentication tokens."
4646
4646
  },
@@ -4654,6 +4654,22 @@
4654
4654
  "fqn": "aws-cdk-lib.aws_secretsmanager.Secret"
4655
4655
  }
4656
4656
  },
4657
+ {
4658
+ "docs": {
4659
+ "remarks": "Should be empty after setup has been completed.",
4660
+ "stability": "experimental",
4661
+ "summary": "Setup secret used to authenticate user for our setup wizard."
4662
+ },
4663
+ "immutable": true,
4664
+ "locationInModule": {
4665
+ "filename": "src/secrets.ts",
4666
+ "line": 32
4667
+ },
4668
+ "name": "setup",
4669
+ "type": {
4670
+ "fqn": "aws-cdk-lib.aws_secretsmanager.Secret"
4671
+ }
4672
+ },
4657
4673
  {
4658
4674
  "docs": {
4659
4675
  "stability": "experimental",
@@ -4673,6 +4689,6 @@
4673
4689
  "symbolId": "src/secrets:Secrets"
4674
4690
  }
4675
4691
  },
4676
- "version": "0.0.13",
4677
- "fingerprint": "HWkQX0qLnjcLcPlC1yPdvDaoLc3rEPauFhw6KoEa4fg="
4692
+ "version": "0.1.1",
4693
+ "fingerprint": "yldbg+9mKQVf9f26Ci6T0YQ+04c90i5jyGEi+VVliCk="
4678
4694
  }
package/API.md CHANGED
@@ -924,6 +924,7 @@ Any object.
924
924
  | <code><a href="#@cloudsnorkel/cdk-github-runners.Secrets.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. |
925
925
  | <code><a href="#@cloudsnorkel/cdk-github-runners.Secrets.property.github">github</a></code> | <code>aws-cdk-lib.aws_secretsmanager.Secret</code> | Authentication secret for GitHub containing either app details or personal authentication token. |
926
926
  | <code><a href="#@cloudsnorkel/cdk-github-runners.Secrets.property.githubPrivateKey">githubPrivateKey</a></code> | <code>aws-cdk-lib.aws_secretsmanager.Secret</code> | GitHub app private key. Not needed when using personal authentication tokens. |
927
+ | <code><a href="#@cloudsnorkel/cdk-github-runners.Secrets.property.setup">setup</a></code> | <code>aws-cdk-lib.aws_secretsmanager.Secret</code> | Setup secret used to authenticate user for our setup wizard. |
927
928
  | <code><a href="#@cloudsnorkel/cdk-github-runners.Secrets.property.webhook">webhook</a></code> | <code>aws-cdk-lib.aws_secretsmanager.Secret</code> | Webhook secret used to confirm events are coming from GitHub and nowhere else. |
928
929
 
929
930
  ---
@@ -967,7 +968,21 @@ public readonly githubPrivateKey: Secret;
967
968
 
968
969
  GitHub app private key. Not needed when using personal authentication tokens.
969
970
 
970
- This secret is meant to be edited by the user after being created.
971
+ This secret is meant to be edited by the user after being created. It is separate than the main GitHub secret because inserting private keys into JSON is hard.
972
+
973
+ ---
974
+
975
+ ##### `setup`<sup>Required</sup> <a name="setup" id="@cloudsnorkel/cdk-github-runners.Secrets.property.setup"></a>
976
+
977
+ ```typescript
978
+ public readonly setup: Secret;
979
+ ```
980
+
981
+ - *Type:* aws-cdk-lib.aws_secretsmanager.Secret
982
+
983
+ Setup secret used to authenticate user for our setup wizard.
984
+
985
+ Should be empty after setup has been completed.
971
986
 
972
987
  ---
973
988
 
package/README.md CHANGED
@@ -10,22 +10,22 @@
10
10
 
11
11
  Use this CDK construct to create ephemeral [self-hosted GitHub runners][1] on-demand inside your AWS account.
12
12
 
13
- * Easy to configure GitHub integration
13
+ * Easy to configure GitHub integration with a web-based interface
14
14
  * Customizable runners with decent defaults
15
- * Supports multiple runner configurations controlled by labels
15
+ * Multiple runner configurations controlled by labels
16
16
  * Everything fully hosted in your account
17
17
 
18
18
  Self-hosted runners in AWS are useful when:
19
19
 
20
20
  * You need easy access to internal resources in your actions
21
21
  * You want to pre-install some software for your actions
22
- * You want to provide some basic AWS API access ([aws-actions/configure-aws-credentials][2] has more security controls)
22
+ * You want to provide some basic AWS API access (but [aws-actions/configure-aws-credentials][2] has more security controls)
23
23
 
24
- Ephemeral 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.
24
+ Ephemeral (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.
25
25
 
26
26
  ## API
27
27
 
28
- Documentation of available constructs and their interface is available on [Constructs Hub][13] in all supported programming languages.
28
+ The best way to browse API documentation is on [Constructs Hub][13]. It is available in all supported programming languages.
29
29
 
30
30
  ## Providers
31
31
 
@@ -72,7 +72,7 @@ You can also create your own provider by implementing `IRunnerProvider`.
72
72
  4. Deploy your stack
73
73
  5. Look for the status command output similar to `aws --region us-east-1 lambda invoke --function-name status-XYZ123 status.json`
74
74
  6. Execute the status command (you may need to specify `--profile` too) and open the resulting `status.json` file
75
- 7. [Setup GitHub](SETUP_GITHUB.md) integration as an app or with personal access token
75
+ 7. 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
76
76
  8. Run status command again to confirm `github.auth.status` and `github.webhook.status` are OK
77
77
  9. Trigger a GitHub action that has a `self-hosted` label with `runs-on: [self-hosted, linux, codebuild]` or similar
78
78
  10. If the action is not successful, see [troubleshooting](#Troubleshooting)
@@ -140,8 +140,9 @@ app.synth();
140
140
  1. Always start with the status function, make sure no errors are reported, and confirm all status codes are OK
141
141
  2. Confirm the webhook Lambda was called by visiting the URL in `troubleshooting.webhookHandlerUrl` from `status.json`
142
142
  1. If it's not called or logs errors, confirm the webhook settings on the GitHub side
143
- 2. If you see too many errors, make sure you're only sending `workflow_job` events
144
- 3. Check execution details of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`
143
+ 2. If you see too many errors, make sure you're only sending `workflow_job` events
144
+ 3. When using GitHub app, make sure there are active installation in `github.auth.app.installations`
145
+ 4. Check execution details of the orchestrator step function by visiting the URL in `troubleshooting.stepFunctionUrl` from `status.json`
145
146
  1. Use the details tab to find the specific execution of the provider (Lambda, CodeBuild, Fargate, etc.)
146
147
  2. Every step function execution should be successful, even if the runner action inside it failed
147
148
 
package/SETUP_GITHUB.md CHANGED
@@ -1,9 +1,23 @@
1
1
  # Setup GitHub
2
2
 
3
- Integration with GitHub can be done using an [app][9] or [personal access token][10]. Using an app allows more fine-grained access control. Personal access tokens are easier to set up but belong to a user instead of an organization.
3
+ Integration with GitHub can be done using an [app](#app-authentication) or [personal access token](#personal-access-token). Using an app allows more fine-grained access control. Using an app is easier with the setup wizard.
4
4
 
5
5
  ## App Authentication
6
6
 
7
+ ### Setup Wizard
8
+
9
+ 1. Open the URL in `github.setup.url` from `status.json`
10
+ 2. If you want to create an app for your personal repositories, click the Create button under New Personal App
11
+ 3. If you want to create an app for your organization:
12
+ 1. Find the New Organization App section
13
+ 2. Type in the organization name in organization slug (ORGANIZATION from https://github.com/ORGANIZATION/REPO)
14
+ 3. Click the Create button
15
+ 4. Follow the instructions on GitHub
16
+ 5. When brought back to the setup wizard, click the install link
17
+ 6. Install the new app on your desired repositories
18
+
19
+ ### Manually
20
+
7
21
  1. Decide if you want to create a personal app or an organization app
8
22
  1. For a personal app use https://github.com/settings/apps/new
9
23
  2. For an organization app use https://github.com/organizations/MY_ORG/settings/apps/new after replacing `MY_ORG` with your GitHub organization name
@@ -18,19 +32,11 @@ Integration with GitHub can be done using an [app][9] or [personal access token]
18
32
  1. Workflow job
19
33
  6. Under "Where can this GitHub App be installed?" select "Only on this account"
20
34
  7. Click the Create button
21
- 8. From the new app page:
22
- 1. Write down the app id and client id
23
- 2. Click generate new client secret and write it down
24
- 3. Generate a private key and save the downloaded key
25
- 9. On the top left go to Install App page and:
26
- 1. Install the app on the desired account or organization
27
- 2. Copy the installation id number from the URL and write it down (e.g. if the URL is https://github.com/settings/installations/123456, your installation id is 123456)
35
+ 8. From the new app page generate a private key and save the downloaded key
36
+ 9. On the top left go to Install App page and install the app on the desired account or organization
28
37
  10. Open the URL in `github.auth.secretUrl` from `status.json` and edit the secret value
29
38
  1. If you're using a self-hosted GitHub instance, put its domain in `domain` (e.g. `github.mycompany.com`)
30
39
  2. Put the new application id in `appId` (e.g. `34789562`)
31
- 3. Put the client id in `clientId` (e.g. `Iv1.0beef123456`)
32
- 4. Put the client secret in `clientSecret` (e.g. `4e2b66fab69065001500697b0d751beb033a3deb`)
33
- 5. Put the installation id you copied from the URL in `installationId` (e.g. `123456`)
34
40
  6. Ignore/delete `dummy` and **leave `personalAuthToken` empty**
35
41
  11. Open the URL in `github.auth.privateKeySecretUrl` from `status.json` and edit the secret value
36
42
  1. Open the downloaded private key with any text editor
@@ -38,21 +44,44 @@ Integration with GitHub can be done using an [app][9] or [personal access token]
38
44
 
39
45
  ## Personal Access Token
40
46
 
41
- 1. Create a new token
42
- 1. Go to https://github.com/settings/tokens/new
43
- 2. Choose your expiration date (you will need to replace the token if it expires)
44
- 3. Under scopes select `repo`
45
- 4. Copy the generated token
46
- 2. Open the URL in `github.auth.secretUrl` from `status.json` and edit the secret value
47
- 1. If you're using a self-hosted GitHub instance, put its domain in `domain` (e.g. `github.mycompany.com`)
48
- 2. Put the generated token in `personalAuthToken`
49
- 3. Ignore all other values
50
- 3. Create a webhook
51
- 1. For organizations go to https://github.com/organizations/MY_ORG/settings/hooks after replacing `MY_ORG` with your GitHub organization name
52
- 2. For enterprise go to https://github.com/enterprises/MY_ENTERPRISE/settings/hooks after replacing `MY_ENTERPRISE` with your GitHub enterprise name
53
- 3. Otherwise, you can create one per repository in your repository settings under Webhooks
54
- 4. Configure the webhook:
55
- 1. For Webhook URL use the value of `github.webhook.url` from `status.json`
56
- 2. Open the URL in `github.webhook.secretUrl` from `status.json`, retrieve the secret value, and use it for webhook secret
57
- 3. Make sure content type is set to JSON
58
- 4. Select individual jobs and select only Workflow jobs
47
+ ### Create Token
48
+
49
+ 1. Go to https://github.com/settings/tokens/new
50
+ 2. Choose your expiration date (you will need to replace the token if it expires)
51
+ 3. Under scopes select `repo`
52
+ 4. Copy the generated token
53
+
54
+ ### Set Token
55
+
56
+ #### Setup Wizard
57
+
58
+ 1. Open the URL in `github.setup.url` from `status.json`
59
+ 2. Enter your personal access token under Using Personal Access Token
60
+ 3. Click the Set button
61
+
62
+ #### Manually
63
+
64
+ 1. Open the URL in `github.auth.secretUrl` from `status.json` and edit the secret value
65
+ 2. If you're using a self-hosted GitHub instance, put its domain in `domain` (e.g. `github.mycompany.com`)
66
+ 3. Put the generated token in `personalAuthToken`
67
+ 4. Ignore all other values
68
+
69
+ ### Setup Webhook
70
+
71
+ 1. For organizations go to https://github.com/organizations/MY_ORG/settings/hooks after replacing `MY_ORG` with your GitHub organization name
72
+ 2. For enterprise go to https://github.com/enterprises/MY_ENTERPRISE/settings/hooks after replacing `MY_ENTERPRISE` with your GitHub enterprise name
73
+ 3. Otherwise, you can create one per repository in your repository settings under Webhooks
74
+ 4. Configure the webhook:
75
+ 1. For Webhook URL use the value of `github.webhook.url` from `status.json`
76
+ 2. Open the URL in `github.webhook.secretUrl` from `status.json`, retrieve the secret value, and use it for webhook secret
77
+ 3. Make sure content type is set to JSON
78
+ 4. Select individual jobs and select only Workflow jobs
79
+
80
+ ## Resetting Setup Wizard
81
+
82
+ If the setup wizard tells you setup has already been completed or if `github.setup.status` is completed, or if `github.setup.url` is empty:
83
+
84
+ 1. Open the URL in `github.setup.secretUrl` from `status.json`
85
+ 2. Edit the secret
86
+ 3. Put a new random value in `token`
87
+ 4. Run status function again to get the new URL
package/changelog.md CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
- ### [0.0.13](https://github.com/CloudSnorkel/cdk-github-runners/compare/v0.0.12...v0.0.13) (2022-05-31)
2
+ ### [0.1.1](https://github.com/CloudSnorkel/cdk-github-runners/compare/v0.1.0...v0.1.1) (2022-06-04)
3
3
 
4
4
 
5
- ### Bug Fixes
5
+ ### Features
6
6
 
7
- * Support building on Apple Silicon / Arm64 platforms ([#22](https://github.com/CloudSnorkel/cdk-github-runners/issues/22)) ([544bae0](https://github.com/CloudSnorkel/cdk-github-runners/commit/544bae0752729d4ba657b575023c483b141b6906))
7
+ * Setup wizard for GitHub integration ([#30](https://github.com/CloudSnorkel/cdk-github-runners/issues/30)) ([38ce153](https://github.com/CloudSnorkel/cdk-github-runners/commit/38ce1538de0fd46c8f9dfec5ef17e3cd58cfbd3b)), closes [#6](https://github.com/CloudSnorkel/cdk-github-runners/issues/6)
@@ -12509,33 +12509,42 @@ var require_dist_node15 = __commonJS({
12509
12509
  // src/lambdas/github.ts
12510
12510
  var import_auth_app = __toESM(require_dist_node12());
12511
12511
  var import_core = __toESM(require_dist_node15());
12512
+
12513
+ // src/lambdas/helpers.ts
12512
12514
  var AWS = __toESM(require("aws-sdk"));
12513
12515
  var sm = new AWS.SecretsManager();
12516
+ async function getSecretValue(arn) {
12517
+ if (!arn) {
12518
+ throw new Error("Missing secret ARN");
12519
+ }
12520
+ const secret = await sm.getSecretValue({ SecretId: arn }).promise();
12521
+ if (!secret.SecretString) {
12522
+ throw new Error(`No SecretString in ${arn}`);
12523
+ }
12524
+ return secret.SecretString;
12525
+ }
12526
+ async function getSecretJsonValue(arn) {
12527
+ return JSON.parse(await getSecretValue(arn));
12528
+ }
12529
+
12530
+ // src/lambdas/github.ts
12514
12531
  function baseUrlFromDomain(domain) {
12515
12532
  if (domain == "github.com") {
12516
12533
  return "https://api.github.com";
12517
12534
  }
12518
12535
  return `https://${domain}/api/v3`;
12519
12536
  }
12520
- async function getOctokit() {
12537
+ async function getOctokit(installationId) {
12521
12538
  if (!process.env.GITHUB_SECRET_ARN || !process.env.GITHUB_PRIVATE_KEY_SECRET_ARN) {
12522
12539
  throw new Error("Missing environment variables");
12523
12540
  }
12524
- const secret = await sm.getSecretValue({
12525
- SecretId: process.env.GITHUB_SECRET_ARN
12526
- }).promise();
12527
- if (!secret.SecretString) {
12528
- throw new Error(`No secret string in ${process.env.GITHUB_SECRET_ARN}`);
12529
- }
12530
- const githubSecrets = JSON.parse(secret.SecretString);
12541
+ const githubSecrets = await getSecretJsonValue(process.env.GITHUB_SECRET_ARN);
12531
12542
  let baseUrl = baseUrlFromDomain(githubSecrets.domain);
12532
12543
  let token;
12533
12544
  if (githubSecrets.personalAuthToken) {
12534
12545
  token = githubSecrets.personalAuthToken;
12535
12546
  } else {
12536
- const privateKey = (await sm.getSecretValue({
12537
- SecretId: process.env.GITHUB_PRIVATE_KEY_SECRET_ARN
12538
- }).promise()).SecretString;
12547
+ const privateKey = await getSecretValue(process.env.GITHUB_PRIVATE_KEY_SECRET_ARN);
12539
12548
  const appOctokit = new import_core.Octokit({
12540
12549
  baseUrl,
12541
12550
  authStrategy: import_auth_app.createAppAuth,
@@ -12546,7 +12555,7 @@ async function getOctokit() {
12546
12555
  });
12547
12556
  token = (await appOctokit.auth({
12548
12557
  type: "installation",
12549
- installationId: githubSecrets.installationId
12558
+ installationId
12550
12559
  })).token;
12551
12560
  }
12552
12561
  const octokit = new import_core.Octokit({
@@ -12580,7 +12589,7 @@ async function getRunnerId(octokit, owner, repo, name) {
12580
12589
  }
12581
12590
  }
12582
12591
  exports.handler = async function(event) {
12583
- const { octokit } = await getOctokit();
12592
+ const { octokit } = await getOctokit(event.installationId);
12584
12593
  await octokit.request("POST /repos/{owner}/{repo}/actions/runs/{runId}/cancel", {
12585
12594
  owner: event.owner,
12586
12595
  repo: event.repo,