Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a7ac90a
Ensure we don't re-use the same names for runner groups
deiga Jul 3, 2026
f11c0f1
Refactor to us `ConfigStateChecks` in `creates_hosted_runners_without…
deiga Jul 4, 2026
c43fab2
Refactor `creates_hosted_runner_with_optional_parameters` to use `Con…
deiga Jul 5, 2026
e04667c
Refactor `updates_hosted_runner_configuration` to use `ConfigStateChe…
deiga Jul 5, 2026
614d7d4
Refactor `updates_size_field` to use `ConfigStateChecks` and `ConfigP…
deiga Jul 5, 2026
4ca1685
Refactor `imports_hosted_runner` to use `ConfigStateChecks`
deiga Jul 5, 2026
ce15f15
Refactor `deletes_hosted_runner` to use `ConfigStateChecks`
deiga Jul 5, 2026
ef0e95f
Ensure `make sweep` clears all resources by default
deiga Jul 5, 2026
ef20a4c
Add sweeper for Org Actions Runner Groups
deiga Jul 5, 2026
29234d0
Refactor to use a single test runner group for all actions runner tests
deiga Jul 5, 2026
976cb5e
Ensure sweeper waits correctly for runner group runner deletions
deiga Jul 5, 2026
692816f
Refactor `resource_github_actions_hosted_runner.go` to use `go-github…
deiga Jul 5, 2026
7ddf645
Refactor `resource_github_actions_hosted_runner.go` to use Context-aw…
deiga Jul 5, 2026
1920126
Refactor to use `tflog`
deiga Jul 5, 2026
4d04422
Address linter issues
deiga Jul 5, 2026
6570a3a
Reduce test cleanup time by having less runners to delete
deiga Jul 5, 2026
2abbbd4
Address review comments
deiga Jul 8, 2026
5536de9
Address Copilot review comments
deiga Jul 8, 2026
e808920
Address review comments
deiga Jul 10, 2026
9daec98
Update RESOURCES file
deiga Jul 10, 2026
87fa346
Update to use generated docs
deiga Jul 10, 2026
08c2677
Cleanup test templates
deiga Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SWEEP?=repositories,teams
SWEEP?=all
PKG_NAME=github
TESTACC?=./$(PKG_NAME)/...

Expand Down Expand Up @@ -81,7 +81,7 @@ testacc:

sweep:
@echo "WARNING: This will destroy infrastructure. Use only in development accounts."
go test $(TESTACC) -v -sweep=$(SWEEP) $(SWEEPARGS)
go test ./github -v -sweep=$(SWEEP) $(SWEEPARGS)

generatedocs:
@cd tools; go generate ./...
Expand Down
2 changes: 1 addition & 1 deletion RESOURCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ The overall status of each resource or data source is captured in this document
| --- | --- | --- | --- | --- | --- | --- | --- |
| `github_actions_environment_secret` | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
| `github_actions_environment_variable` | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
| `github_actions_hosted_runner` | | | | | | | |
| `github_actions_hosted_runner` | | | | | | | |
| `github_actions_organization_oidc_subject_claim_customization_template` | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
| `github_actions_organization_permissions` | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
| `github_actions_organization_secret` | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
Expand Down
172 changes: 75 additions & 97 deletions docs/resources/actions_hosted_runner.md
Original file line number Diff line number Diff line change
@@ -1,153 +1,131 @@
---
page_title: "github_actions_hosted_runner (Resource) - GitHub"
subcategory: ""
description: |-
Creates and manages GitHub-hosted runners within a GitHub organization
This resource allows you to create and manage GitHub-hosted runners within your GitHub organization. You must have admin access to an organization to use this resource.
---

# github_actions_hosted_runner (Resource)

This resource allows you to create and manage GitHub-hosted runners within your GitHub organization. You must have admin access to an organization to use this resource.

GitHub-hosted runners are fully managed virtual machines that run your GitHub Actions workflows. Unlike self-hosted runners, GitHub handles the infrastructure, maintenance, and scaling.
## Notes

## Example Usage
- This resource is **organization-only** and cannot be used with individual accounts.
- Image IDs for GitHub-owned images are numeric strings (e.g., "2306" for Ubuntu Latest 24.04), not names like "ubuntu-latest".
- Deletion of hosted runners is asynchronous. The provider will poll for up to 10 minutes (configurable via timeouts) to confirm deletion.
- Runner creation and updates may take several minutes as GitHub provisions the infrastructure.

### Basic Usage
## Getting Available Images and Sizes

```terraform
resource "github_actions_runner_group" "example" {
name = "example-runner-group"
visibility = "all"
}
To get a list of available images:

resource "github_actions_hosted_runner" "example" {
name = "example-hosted-runner"
```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/orgs/YOUR_ORG/actions/hosted-runners/images/github-owned
```

image {
id = "2306"
source = "github"
}
To get available machine sizes:

size = "4-core"
runner_group_id = github_actions_runner_group.example.id
}
```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/orgs/YOUR_ORG/actions/hosted-runners/machine-sizes
```

### Advanced Usage with Optional Parameters
## Example Usage

### Advanced Usage

```terraform
resource "github_actions_runner_group" "advanced" {
name = "advanced-runner-group"
visibility = "selected"
resource "github_actions_runner_group" "example" {
name = "example-runner-group"
visibility = "all"
}

resource "github_actions_hosted_runner" "advanced" {
name = "advanced-hosted-runner"
resource "github_actions_hosted_runner" "example" {
name = "example-hosted-runner"

image {
id = "2306"
source = "github"
}

size = "8-core"
runner_group_id = github_actions_runner_group.advanced.id
runner_group_id = github_actions_runner_group.example.id
maximum_runners = 10
public_ip_enabled = true
}
```

## Argument Reference
<!-- schema generated by tfplugindocs -->
## Schema

The following arguments are supported:
### Required

- `name` - (Required) Name of the hosted runner. Must be between 1 and 64 characters and may only contain alphanumeric characters, '.', '-', and '_'.
- `image` - (Required) Image configuration for the hosted runner. Cannot be changed after creation. Block supports:
- `id` - (Required) The image ID. For GitHub-owned images, use numeric IDs like "2306" for Ubuntu Latest 24.04. To get available images, use the GitHub API: `GET /orgs/{org}/actions/hosted-runners/images/github-owned`.
- `source` - (Optional) The image source. Valid values are "github", "partner", or "custom". Defaults to "github".
- `size` - (Required) Machine size for the hosted runner (e.g., "4-core", "8-core"). Can be updated to scale the runner. To list available sizes, use the GitHub API: `GET /orgs/{org}/actions/hosted-runners/machine-sizes`.
- `runner_group_id` - (Required) The ID of the runner group to assign this runner to.
- `maximum_runners` - (Optional) Maximum number of runners to scale up to. Runners will not auto-scale above this number. Use this setting to limit costs.
- `public_ip_enabled` - (Optional) Whether to enable static public IP for the runner. Note there are account limits. To list limits, use the GitHub API: `GET /orgs/{org}/actions/hosted-runners/limits`. Defaults to false.
- `image_version` - (Optional) The version of the runner image to deploy. This is only relevant for runners using custom images.
- `image` (Block List, Min: 1, Max: 1) Image configuration for the hosted runner. Cannot be changed after creation. (see [below for nested schema](#nestedblock--image))
- `name` (String) Name of the hosted runner. Must be between 1 and 64 characters and may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'.
- `runner_group_id` (Number) The ID of the runner group to assign this runner to.
- `size` (String) Machine size for the hosted runner (e.g., `4-core`, `8-core`). Can be updated to scale the runner. To list available sizes, use the GitHub API: `GET /orgs/{org}/actions/hosted-runners/machine-sizes`.

## Timeouts
### Optional

The `timeouts` block allows you to specify timeouts for certain actions:
- `image_gen` (Boolean) Whether this runner should be used to generate custom images. Cannot be changed after creation.
- `image_version` (String) The version of the runner image to deploy. This is only relevant for runners using custom images.
- `maximum_runners` (Number) Maximum number of runners to scale up to. Runners will not auto-scale above this number. Use this setting to limit costs.
- `public_ip_enabled` (Boolean) Whether to enable static public IP for the runner. Note there are account limits. To list limits, use the GitHub API: `GET /orgs/{org}/actions/hosted-runners/limits`. Defaults to false.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

- `delete` - (Defaults to 10 minutes) Used for waiting for the hosted runner deletion to complete.
### Read-Only

Example:
- `id` (String) The hosted runner ID.
- `last_active_on` (String) Timestamp when the runner was last active.
- `machine_size_details` (List of Object) Detailed machine size specifications. (see [below for nested schema](#nestedatt--machine_size_details))
- `platform` (String) Platform of the runner.
- `public_ips` (List of Object) List of public IP ranges assigned to this runner. (see [below for nested schema](#nestedatt--public_ips))
- `status` (String) Current status of the runner.

```terraform
resource "github_actions_hosted_runner" "example" {
name = "example-hosted-runner"
<a id="nestedblock--image"></a>
### Nested Schema for `image`

image {
id = "2306"
source = "github"
}
Required:

size = "4-core"
runner_group_id = github_actions_runner_group.example.id
- `id` (String) The image ID.

timeouts {
delete = "15m"
}
}
```
Optional:

## Attributes Reference
- `source` (String) The image source (github, partner, or custom).

In addition to the arguments above, the following attributes are exported:
Read-Only:

- `id` - The ID of the hosted runner.
- `status` - Current status of the runner (e.g., "Ready", "Provisioning").
- `platform` - Platform of the runner (e.g., "linux-x64", "win-x64").
- `image` - In addition to the arguments above, the image block exports:
- `size_gb` - The size of the image in gigabytes.
- `machine_size_details` - Detailed specifications of the machine size:
- `id` - Machine size identifier.
- `cpu_cores` - Number of CPU cores.
- `memory_gb` - Amount of memory in gigabytes.
- `storage_gb` - Amount of storage in gigabytes.
- `public_ips` - List of public IP ranges assigned to this runner (only if `public_ip_enabled` is true):
- `enabled` - Whether this IP range is enabled.
- `prefix` - IP address prefix.
- `length` - Subnet length.
- `last_active_on` - Timestamp (RFC3339) when the runner was last active.
- `size_gb` (Number) The size of the image in GB.

## Import

Hosted runners can be imported using the runner ID:
<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

```shell
terraform import github_actions_hosted_runner.example 123456
```
Optional:

## Notes
- `delete` (String)

- This resource is **organization-only** and cannot be used with individual accounts.
- The `image` field cannot be changed after the runner is created. Changing it will force recreation of the runner.
- The `size` field can be updated to scale the runner up or down as needed.
- Image IDs for GitHub-owned images are numeric strings (e.g., "2306" for Ubuntu Latest 24.04), not names like "ubuntu-latest".
- Deletion of hosted runners is asynchronous. The provider will poll for up to 10 minutes (configurable via timeouts) to confirm deletion.
- Runner creation and updates may take several minutes as GitHub provisions the infrastructure.
- Static public IPs are subject to account limits. Check your organization's limits before enabling.

## Getting Available Images and Sizes
<a id="nestedatt--machine_size_details"></a>
### Nested Schema for `machine_size_details`

To get a list of available images:
Read-Only:

```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/orgs/YOUR_ORG/actions/hosted-runners/images/github-owned
```
- `cpu_cores` (Number)
- `id` (String)
- `memory_gb` (Number)
- `storage_gb` (Number)

To get available machine sizes:

```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/orgs/YOUR_ORG/actions/hosted-runners/machine-sizes
```
<a id="nestedatt--public_ips"></a>
### Nested Schema for `public_ips`

Read-Only:

- `enabled` (Boolean)
- `length` (Number)
- `prefix` (String)
18 changes: 0 additions & 18 deletions examples/resources/actions_hosted_runner/example_2.tf

This file was deleted.

15 changes: 0 additions & 15 deletions examples/resources/actions_hosted_runner/example_3.tf

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ resource "github_actions_hosted_runner" "example" {
source = "github"
}

size = "4-core"
runner_group_id = github_actions_runner_group.example.id
size = "8-core"
runner_group_id = github_actions_runner_group.example.id
maximum_runners = 10
public_ip_enabled = true
}
32 changes: 32 additions & 0 deletions github/acc_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,38 @@ func mustCreateTestRepository(t *testing.T) *github.Repository {
return repo
}

func mustCreateTestOrganizationActionsRunnerGroup(t *testing.T) *github.RunnerGroup {
t.Helper()

randomID := acctest.RandString(testRandomIDLength)
name := fmt.Sprintf("%s%s", testResourcePrefix, randomID)

req := github.CreateRunnerGroupRequest{
Name: &name,
Visibility: new("all"),
}

runnerGroup, _, err := testAccConf.meta.v3client.Actions.CreateOrganizationRunnerGroup(t.Context(), testAccConf.meta.name, req)
if err != nil {
t.Fatalf("failed to create test organization runner group: %v", err)
}

t.Cleanup(func() {
ctx := context.WithoutCancel(t.Context())
if err := sweepRunnerGroupRunners(ctx, runnerGroup); err != nil {
t.Logf("failed to delete runner group runners for %s: %v", runnerGroup.GetName(), err)
}
if _, err := testAccConf.meta.v3client.Actions.DeleteOrganizationRunnerGroup(ctx, testAccConf.meta.name, runnerGroup.GetID()); err != nil {
if err, ok := errors.AsType[*github.ErrorResponse](err); ok && err.Response.StatusCode == 404 {
return
}
t.Logf("failed to delete test organization runner group %s: %v", name, err)
}
})

return runnerGroup
}

func mustAddRepositoryCollaborator(t *testing.T, repo *github.Repository, username string) {
t.Helper()

Expand Down
Loading
Loading