feat: add hosted runner private networking support - #3274
Conversation
|
👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday! We have a process in place for prioritizing and responding to your input. Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labeled with |
|
Your validation commands would not actually run the tests. You should use make testacc and make test |
This comment was marked as resolved.
This comment was marked as resolved.
tag-assistant
left a comment
There was a problem hiding this comment.
Re-review ✅
All previous feedback addressed, plus some nice extras:
Addressed:
- ✅ Shared
runnerGroupNetworkingstruct + helpers inresource_github_actions_runner_group_networking.go— clean dedup - ✅
getRunnerGroupNetworkingnow takes a path string, works for both org and enterprise scopes - ✅ Trailing newline fixed on enterprise docs
- ✅
StatusNotModifiedhandling added togetRunnerGroupNetworking— consistent with the rest of the codebase
Bonus improvements (not requested):
- 🧪 173-line unit test file for all three shared helpers (
get,update,setState) — including 304 handling and null payload for removal. Solid. - 🔧
normalizeEtag()in util.go to handle weak vs strong ETag drift between create and read paths — nice catch, prevents state churn. - 🧪 Unit tests for
normalizeEtagcovering empty, strong, weak, and whitespace cases.
LGTM. Ship it 🚢
There was a problem hiding this comment.
Since you're modifying this file, please migrate the CRUD functions to be Context-aware
There was a problem hiding this comment.
Done — this file now uses context-aware CRUD handlers (CreateContext/ReadContext/UpdateContext/DeleteContext).
…unner group types Add NetworkConfigurationID and HostedRunnersURL fields to EnterpriseRunnerGroup, and NetworkConfigurationID to CreateEnterpriseRunnerGroupRequest and UpdateEnterpriseRunnerGroupRequest to match the GitHub API response schema. These fields already exist on the organization-scoped RunnerGroup type but were missing from the enterprise equivalents. The GitHub API returns both fields on enterprise runner group endpoints (List, Get, Create, Update). Fixes: integrations/terraform-provider-github#3274
|
All review feedback addressed except the raw |
508630f to
022c485
Compare
…etwork configurations
…tation for network settings
…date related documentation
…d unit tests for normalization
# Conflicts: # github/resource_github_actions_runner_group.go # github/resource_github_actions_runner_group_test.go # github/resource_github_enterprise_actions_runner_group.go
- Update to go-github v89 - Use errors.AsType per current repo idiom - Share the state setter and network settings expansion between scopes - Add ForceNew to enterprise_slug so moving scope replaces the resource - Handle 304 Not Modified in Read Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Assign a hosted compute network configuration to an organization or enterprise runner group. The request object is built up front and the optional field is set inside the conditional. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Remove the unused normalizeEtag helper and its test - Remove the runner group unit test file that covered pre-existing helpers - Align network configuration test destroy checks with testAccConf.meta - Replace a removed network configuration by ForceNew, since the API cannot unset the assignment through an update Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Docs in this repo are generated by tfplugindocs from templates/ and examples/, so hand-edited pages under docs/ get overwritten. Add the missing templates and example configurations, document network_configuration_id on both runner groups, and correct the hosted runner example which used a payload key rather than the schema attribute. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The branch had accumulated go.sum entries not required by go.mod. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…urces ctxId is written by many resources but never read; only ctxEtag is consumed by the etag transport. The network configuration resources do not expose an etag attribute, so threading ctxId through was noise. Also align the enterprise import error message with the wording used by the enterprise runner group importer. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The strict linter config used for new code enables forcetypeassert, so unchecked assertions in new code fail CI. Adopt the pattern already used by the organization role data sources: take the provider meta as `m any`, assert it once into a typed `meta`, and use checkOrganizationOK, which returns diagnostics directly rather than an error. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Thanks for the patience on this one, and sorry for the long gap. I've rebuilt the PR against current Scope reductionThe biggest problem with the previous state was that it dragged both runner group resources through an unrelated context/diag migration. Both The Review threads
New resources
They follow the pattern the organization role data sources use: 422s from a cross-scope network settings ID get annotated, since mixing up an org-scoped and an enterprise-scoped
|
| // networkConfigurationRemoved reports whether a hosted compute network configuration was | ||
| // removed from a runner group. The REST API only accepts an explicit null to clear the | ||
| // assignment, which the client library's request type cannot express, so the runner group is | ||
| // replaced instead of leaving the practitioner with a perpetual diff. |
There was a problem hiding this comment.
question: Please elaborate on this.
The API docs don't contain any mention of this and it sounds like an go-github ~bug that the field is omitempty. Could you open a PR there to modify the struct?
| if err = d.Set("network_configuration_id", runnerGroup.GetNetworkConfigurationID()); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
question: Since we're setting the value here, should the field be marked as Computed: true?
There was a problem hiding this comment.
Kept this Optional without Computed intentionally. Reading the configured value back is also needed for refresh/import; it doesn't make the field server-controlled. Optional+Computed would retain the previous assignment when the attribute is omitted, rather than treating omission as a request to remove it. The separate SDK null-serialization thread is still open.
There was a problem hiding this comment.
Resources should never set or change an attribute value without the schema Computed flag.
|
Please also note that some of the resource you modify here are being changed in this PR. It's recommended to use that as a base |
There was a problem hiding this comment.
Pull request overview
These provider review instructions are being used.
Adds enterprise and organization hosted-compute network configuration resources and runner-group associations.
Changes:
- Adds network configuration CRUD, imports, registration, tests, examples, and docs.
- Adds runner-group
network_configuration_idsupport. - Updates hosted-runner networking guidance.
Unresolved issues include create-endpoint contract mismatches, missing organization acceptance coverage, and the unimplemented 304-only error handling described by the PR.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
templates/resources/organization_network_configuration.md.tmpl |
Adds organization resource template. |
templates/resources/enterprise_network_configuration.md.tmpl |
Adds enterprise resource template. |
templates/resources/enterprise_actions_runner_group.md.tmpl |
Documents enterprise networking association. |
templates/resources/actions_runner_group.md.tmpl |
Documents organization networking association. |
templates/resources/actions_hosted_runner.md.tmpl |
Clarifies private networking configuration. |
github/resource_github_organization_network_configuration.go |
Implements organization CRUD and import. |
github/resource_github_organization_network_configuration_test.go |
Adds organization resource acceptance tests. |
github/resource_github_enterprise_network_configuration.go |
Implements enterprise CRUD and import. |
github/resource_github_enterprise_network_configuration_test.go |
Adds enterprise resource acceptance tests. |
github/resource_github_enterprise_actions_runner_group.go |
Adds enterprise runner-group association. |
github/resource_github_enterprise_actions_runner_group_test.go |
Tests enterprise association flows. |
github/resource_github_actions_runner_group.go |
Adds organization runner-group association. |
github/provider.go |
Registers both resources. |
examples/resources/organization_network_configuration/example_1.tf |
Demonstrates organization networking. |
examples/resources/enterprise_network_configuration/example_1.tf |
Demonstrates enterprise networking. |
examples/hosted_runner/main.tf |
Updates public-IP argument. |
docs/resources/organization_network_configuration.md |
Adds generated organization documentation. |
docs/resources/enterprise_network_configuration.md |
Adds generated enterprise documentation. |
docs/resources/enterprise_actions_runner_group.md |
Documents enterprise association. |
docs/resources/actions_runner_group.md |
Documents organization association. |
docs/resources/actions_hosted_runner.md |
Documents private networking placement. |
|
bump @austenstone we would love to see this land! ❤️ |
Preserve the upstream ETag diff handler alongside the networking diff handler instead of declaring CustomizeDiff twice. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Only treat HTTP 304 as a cache hit. Preserve 404 state removal and surface authorization/server failures instead of silently retaining stale networking state. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use API-created network configuration fixtures for runner-group acceptance tests, verify stable IDs on association, and exercise native create/update payloads and refreshed state offline. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve ETag suppression and in-place association updates. Correct descriptions to identify the SDK null-serialization limitation, not an API limitation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use default schema-generated documentation and import examples, validate network settings IDs, share state helpers, and cover computed timestamp refresh and import lifecycles. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Can we keep the configuration resources and runner-group attachment together here? They cover one end-to-end workflow; the unrelated runner-group refactors are gone. The non-SDK inline feedback is addressed. CI and CodeQL need maintainer approval. Native detachment remains blocked on google/go-github#4541 and its release; replacement on removal is not the intended merge-ready behavior. |
| @@ -0,0 +1,4 @@ | |||
| set -euo pipefail | |||
There was a problem hiding this comment.
| set -euo pipefail |
| set -euo pipefail | ||
|
|
There was a problem hiding this comment.
| set -euo pipefail |
| if err = d.Set("network_configuration_id", runnerGroup.GetNetworkConfigurationID()); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
issue: this needs to be Computed
| { | ||
| Config: configWithNetworking, | ||
| ConfigStateChecks: []statecheck.StateCheck{ | ||
| sameID.AddStateValue(resourceName, tfjsonpath.New("id")), |
There was a problem hiding this comment.
question: what's the purpose of this check?
Resolves #2302
Before the change?
Hosted-runner private networking cannot be managed end to end through the provider: network configurations and their runner-group associations need to be managed separately from Terraform.
After the change?
Manage hosted-compute network configurations and runner-group associations at both organization and enterprise scope. Both runner-group POST endpoints accept
network_configuration_id; an extra networking-only PATCH after creation is not required. The previous description was incorrect about that.Not ready to merge: removing an association still replaces the runner group in this branch. google/go-github#4541 adds the explicit-null serialization needed for in-place removal. It needs to be merged and released, then adopted here before replacing the current removal behavior. The REST API already supports null; this is a client-library limitation.
The configuration resources and runner-group integration remain together here. The earlier request to split that scope still needs maintainer agreement.
Implementation and cleanup were substantially AI-assisted with Copilot.
Pull request checklist
Targeted Go 1.26 tests, strict changed-code lint, example formatting, and generated-documentation checks pass locally. Fixture requirements are documented in CONTRIBUTING.md.
Live validation on September 10, 2026, against the implementation in this PR:
nullremoves the enterprise group's association while preserving both its group ID and hosted-runner configuration. This validates the API contract behind the SDK change; it does not mean the provider's removal path is fixed.Enterprise hosted-runner provisioning used the supported enterprise API. The existing
github_actions_hosted_runnerresource is organization-only and rejected an inherited enterprise group ID. Organization access to an enterprise group also required separate repository access within the organization.An older shared network fixture left jobs waiting for a runner to come online; the fresh isolated fixture succeeded. The older fixture's specific failure cause remains unproven, and no shared Azure network or enterprise policy was changed. These local/live runs are separate from the PR's acceptance CI status.
Does this introduce a breaking change?
Please see our docs on breaking changes to help!
Existing configurations without the new attributes retain their behavior. The new association-removal path must become non-destructive before this PR merges.