Skip to content

Commit 8b9e1c7

Browse files
feat: Enterprise-level runners
1 parent 1d57199 commit 8b9e1c7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1194
-224
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This [Terraform](https://www.terraform.io/) module creates the required infrastr
2424
- OS support: Linux (x64/arm64) and Windows
2525
- Multi-Runner: Create multiple runner configurations with a single deployment
2626
- GitHub cloud, GitHub Cloud with Data Residency and GitHub Enterprise Server (GHES) support.
27-
- Org and repo level runners. enterprise level runners are not supported (yet).
27+
- Org and repo level runners. Enterprise level runners are supported via PAT-based authentication.
2828

2929

3030
## Getting started

docs/examples/enterprise.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--8<-- "examples/enterprise/README.md"

docs/getting-started.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ module "github-runner" {
9191
webhook_lambda_zip = "lambdas-download/webhook.zip"
9292
runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip"
9393
runners_lambda_zip = "lambdas-download/runners.zip"
94-
enable_organization_runners = true
94+
95+
runner_registration_level = "org"
9596
}
9697
```
9798

examples/default/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ module "runners" {
5050
# runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip"
5151
# runners_lambda_zip = "../lambdas-download/runners.zip"
5252

53-
enable_organization_runners = true
54-
runner_extra_labels = ["default", "example"]
53+
runner_registration_level = "org"
54+
runner_extra_labels = ["default", "example"]
5555

5656
# enable access to the runners via SSM
5757
enable_ssm_on_runners = true

examples/enterprise/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Enterprise Runner Example
2+
3+
This example demonstrates how to deploy GitHub self-hosted runners at the **Enterprise level** using PAT-based authentication.
4+
5+
## Prerequisites
6+
7+
1. **GitHub Enterprise Account** — You need a GitHub Enterprise Cloud account with admin access.
8+
2. **Enterprise PAT** — Create one or more Personal Access Tokens with the `manage_runners:enterprise` scope:
9+
- Go to your GitHub account settings → Developer settings → Personal access tokens (classic)
10+
- Create a new token with the `manage_runners:enterprise` scope
11+
- Save the token securely — you'll need it for the `enterprise_pat` variable
12+
- **Tip**: To distribute API calls and avoid rate limiting, create multiple PATs (from different accounts if possible) and provide them as a comma-separated string. The Lambda functions will randomly select one PAT per invocation.
13+
3. **Enterprise Webhook** — Configure an enterprise-level webhook to send `workflow_job` events to the module's webhook endpoint. Choose a random secret for the webhook — you'll need it for the `webhook_secret` parameter.
14+
15+
> **Note**: Enterprise runners do **not** require a GitHub App. Only a webhook secret is needed to verify incoming webhook payloads. The PAT handles all GitHub API interactions.
16+
17+
## Configuration
18+
19+
```hcl
20+
module "runners" {
21+
source = "../../"
22+
23+
# Enterprise runner registration
24+
runner_registration_level = "enterprise"
25+
enterprise_slug = "my-enterprise"
26+
27+
# Enterprise PAT — stored in AWS SSM Parameter Store as SecureString
28+
# Single PAT:
29+
enterprise_pat = {
30+
pat = var.enterprise_pat
31+
}
32+
33+
# Multiple PATs (comma-separated) for rate limit distribution:
34+
# enterprise_pat = {
35+
# pat = "ghp_token1,ghp_token2,ghp_token3"
36+
# }
37+
38+
# No GitHub App is required for enterprise runners.
39+
# Only the webhook_secret is needed to verify incoming webhook payloads.
40+
github_app = {
41+
webhook_secret = random_id.random.hex
42+
}
43+
44+
# ... other configuration
45+
}
46+
```
47+
48+
## Variables
49+
50+
| Name | Description | Type | Required |
51+
|------|-------------|------|----------|
52+
| `enterprise_slug` | The slug of the GitHub Enterprise account | string | Yes |
53+
| `enterprise_pat` | PAT with `manage_runners:enterprise` scope | string (sensitive) | Yes |
54+
| `environment` | Environment name prefix | string | No |
55+
| `aws_region` | AWS region for deployment | string | No |
56+
57+
The `github_app` block only requires `webhook_secret` — the `key_base64` and `id` fields are **not** needed for enterprise runners.
58+
59+
## Verification
60+
61+
After deployment:
62+
63+
1. Check the webhook endpoint in the Terraform outputs
64+
2. Configure the enterprise webhook to point to the endpoint
65+
3. Trigger a workflow run in any repository under the enterprise
66+
4. Verify runners appear in **Enterprise Settings → Actions → Runners**
67+
68+
## Migration from Organization Runners
69+
70+
If you're migrating from organization-level runners:
71+
72+
```hcl
73+
# Before
74+
enable_organization_runners = true
75+
76+
# After
77+
runner_registration_level = "enterprise"
78+
enterprise_slug = "my-enterprise"
79+
enterprise_pat = {
80+
pat = var.enterprise_pat
81+
}
82+
```

examples/enterprise/main.tf

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
locals {
2+
environment = var.environment != null ? var.environment : "enterprise"
3+
aws_region = var.aws_region
4+
}
5+
6+
resource "random_id" "random" {
7+
byte_length = 20
8+
}
9+
10+
module "base" {
11+
source = "../base"
12+
13+
prefix = local.environment
14+
aws_region = local.aws_region
15+
}
16+
17+
module "runners" {
18+
source = "../../"
19+
create_service_linked_role_spot = true
20+
aws_region = local.aws_region
21+
vpc_id = module.base.vpc.vpc_id
22+
subnet_ids = module.base.vpc.private_subnets
23+
24+
prefix = local.environment
25+
tags = {
26+
Project = "Enterprise Runners"
27+
}
28+
29+
# Enterprise runners do not require a GitHub App.
30+
# Only the webhook_secret is needed to verify incoming webhook payloads.
31+
github_app = {
32+
webhook_secret = random_id.random.hex
33+
}
34+
35+
# Enterprise runner registration level
36+
runner_registration_level = "enterprise"
37+
enterprise_slug = var.enterprise_slug
38+
39+
# Enterprise PAT for authentication
40+
enterprise_pat = {
41+
pat = var.enterprise_pat
42+
}
43+
44+
# Runner labels
45+
runner_extra_labels = ["enterprise", "example"]
46+
47+
# enable access to the runners via SSM
48+
enable_ssm_on_runners = true
49+
50+
instance_types = ["m7a.large", "m5.large"]
51+
52+
# override delay of events in seconds
53+
delay_webhook_event = 5
54+
runners_maximum_count = 5
55+
56+
# override scaling down
57+
scale_down_schedule_expression = "cron(* * * * ? *)"
58+
59+
enable_user_data_debug_logging_runner = true
60+
}
61+

examples/enterprise/outputs.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
output "runners" {
2+
value = {
3+
lambda_syncer_name = module.runners.binaries_syncer.lambda.function_name
4+
}
5+
}
6+
7+
output "webhook_endpoint" {
8+
value = module.runners.webhook.endpoint
9+
}
10+
11+
output "webhook_secret" {
12+
sensitive = true
13+
value = random_id.random.hex
14+
}
15+

examples/enterprise/providers.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
provider "aws" {
2+
region = local.aws_region
3+
4+
default_tags {
5+
tags = {
6+
Example = local.environment
7+
}
8+
}
9+
}
10+

examples/enterprise/variables.tf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
variable "enterprise_slug" {
2+
description = "The slug of the GitHub Enterprise account. Example: 'my-enterprise'."
3+
type = string
4+
}
5+
6+
variable "enterprise_pat" {
7+
description = "Personal Access Token with 'manage_runners:enterprise' scope for enterprise runner management."
8+
type = string
9+
sensitive = true
10+
}
11+
12+
variable "environment" {
13+
description = "Environment name, used as prefix."
14+
type = string
15+
default = null
16+
}
17+
18+
variable "aws_region" {
19+
description = "AWS region."
20+
type = string
21+
default = "eu-west-1"
22+
}
23+

examples/enterprise/versions.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = ">= 6.21"
6+
}
7+
local = {
8+
source = "hashicorp/local"
9+
version = "~> 2.0"
10+
}
11+
random = {
12+
source = "hashicorp/random"
13+
version = "~> 3.0"
14+
}
15+
}
16+
required_version = ">= 1.3.0"
17+
}
18+

0 commit comments

Comments
 (0)