terraform-provider-github
terraform-provider-github copied to clipboard
Repository environment creation error
Terraform Version
Terraform v1.0.7
Affected Resource(s)
github_repository_environment
Terraform Configuration Files
resource "github_repository_environment" "my_repo_environments" {
for_each = toset([
"production",
"staging",
])
repository = github_repository.my_repo.name
environment = each.key
}
Debug Output
Expected Behavior
Create an environment
Actual Behavior
Got this errore (both staging and production)
╷
│ Error: PUT https://api.github.com/repos/my-org/my-repo/environments/production: 422 Fail to create protected rule, please ensure billing plan include protected branch gate. []
│
Steps to Reproduce
Please list the steps required to reproduce the issue, for example:
terraform apply
Work arround
If I set the "Deployment branches" in the GUI (protected branches), import the resource and add the following config terraform terminates well.
deployment_branch_policy {
protected_branches = true
custom_branch_policies = false
}
This is effecting me in Pulumi, doing a refresh does not seem to import the manually updated state so the workaround did not work for me. Here is a relevant thread in GitHub community that might help bring some attention to the issue if its on their end. https://github.com/orgs/community/discussions/30201
This is effecting me in Pulumi, doing a refresh does not seem to import the manually updated state so the workaround did not work for me. Here is a relevant thread in GitHub community that might help bring some attention to the issue if its on their end. https://github.com/orgs/community/discussions/30201
ok, so probably is not a terraform problem but github api
TLDR; I suppose is wait_timer parameter that has been sent as 0 even if omited in terraform
Using github provider I receive the same 422 error: "422 Fail to create protected rule, please ensure billing plan include protected branch gate. []"
resource "github_repository_environment" "project_repo_env" {
repository = data.github_repository.project_repo.name
environment = var.gh_project_environment
}
Debugging a Terraform apply: wait_timer: 0 was inserted and that causes the error
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: ---[ REQUEST ]---------------------------------------
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: PUT /repos/atlastechnol/web-fm-consumer/environments/labs HTTP/1.1
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: Host: api.github.com
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: User-Agent: go-github/v47.0.0
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: Content-Length: 66
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: Accept: application/vnd.github.v3+json
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: Content-Type: application/json
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: Accept-Encoding: gzip
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe:
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: {
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: "wait_timer": 0,
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: "reviewers": null,
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: "deployment_branch_policy": null
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: }
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe:
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: -----------------------------------------------------
[DEBUG] Github API Response Details:
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: ---[ RESPONSE ]--------------------------------------
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: HTTP/2.0 422 Unprocessable Entity
{
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: "message": "Fail to create protected rule, please ensure billing plan include protected branch gate.",
[DEBUG] plugin.terraform-provider-github_v4.31.0.exe: "documentation_url": "https://docs.github.com/rest/reference/repos#create-or-update-an-environment"
}
Using github api it works well
const result = await request('PUT /repos/{owner}/{repo}/environments/{environment_name}', {
headers: {
authorization: "token 0000000000000000000000000",
},
owner: 'roger',
repo: 'my-repo',
environment_name: 'develop'
})
I suppose is "wait_timer" parameter that has been sent even if omited, because when I run with this parameter shows the same error
const result = await request('PUT /repos/{owner}/{repo}/environments/{environment_name}', {
headers: {
authorization: "token 0000000000000000000000000",
},
owner: 'roger',
repo: 'my-repo',
environment_name: 'develop',
wait_timer: null
})
Relevant Terraform provider Go file: https://github.com/integrations/terraform-provider-github/blame/main/vendor/github.com/google/go-github/v47/github/repos_environments.go Line 147-172
// MarshalJSON implements the json.Marshaler interface.
// As the only way to clear a WaitTimer is to set it to 0, a missing WaitTimer object should default to 0, not null.
func (c *CreateUpdateEnvironment) MarshalJSON() ([]byte, error) {
type Alias CreateUpdateEnvironment
if c.WaitTimer == nil {
c.WaitTimer = Int(0)
}
return json.Marshal(&struct {
*Alias
}{
Alias: (*Alias)(c),
})
}
// CreateUpdateEnvironment represents the fields required for the create/update operation
// following the Create/Update release example.
// See https://github.com/google/go-github/issues/992 for more information.
// Removed omitempty here as the API expects null values for reviewers and deployment_branch_policy to clear them.
type CreateUpdateEnvironment struct {
WaitTimer *int `json:"wait_timer"`
Reviewers []*EnvReviewers `json:"reviewers"`
DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"`
}
Seems due to this being a new feature for GitHub Teams when the relevant Terraform provider code was written they didn't count for a use case where a user would want to create environments but have no access to the branch protection rule feature.
We're also struggling with this. The environments do get created, but tf errors out with a 422 each time, so state is not updated.
Is this something that we can expect a quick fix for?? The jobs are left in a failed state always due to this issue.
There's a work around, this is how we solved it:
Because it only fails on create/update you can create the environments manually or via API (we had quite a few to create, so we opted for this, very straightforward to use) and then import the environments into your code.
Obviously this is not a long term solution, but can work if the missing feature is blocking you.
@AnitaErnszt what version are you importing with? I'm also impacted by this 422 Fail to create protected rule to create the environment and then finally add some secrets to it. I created the environment through the UI manually, but every time I import, it fails with the following:
Stack trace from the terraform-provider-github_v5.2.0 plugin:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x78 pc=0x19f7eb0]
goroutine 64 [running]:
github.com/integrations/terraform-provider-github/v5/github.resourceGithubRepositoryEnvironmentRead(0xc0002288c0, {0x1a86d00?, 0xc00013ab80?})
github.com/integrations/terraform-provider-github/v5/github/resource_github_repository_environment.go:125 +0x490
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Resource).RefreshWithoutUpgrade(0xc000781d60, 0xc000181d10, {0x1a86d00, 0xc00013ab80})
github.com/hashicorp/[email protected]/helper/schema/resource.go:470 +0x1aa
github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ReadResource(0xc000116a50, {0xc00058d0e0?, 0x10b3ba6?}, 0xc00058d0e0)
github.com/hashicorp/[email protected]/internal/helper/plugin/grpc_provider.go:535 +0x34b
github.com/hashicorp/terraform-plugin-sdk/internal/tfplugin5._Provider_ReadResource_Handler({0x1c2a1c0?, 0xc000116a50}, {0x1e89730, 0xc00017a120}, 0xc00058d080, 0x0)
github.com/hashicorp/[email protected]/internal/tfplugin5/tfplugin5.pb.go:3269 +0x170
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0002b0380, {0x1e8cea0, 0xc000682340}, 0xc00097a6c0, 0xc0003acc30, 0x2534710, 0x0)
google.golang.org/[email protected]/server.go:1283 +0xcfd
google.golang.org/grpc.(*Server).handleStream(0xc0002b0380, {0x1e8cea0, 0xc000682340}, 0xc00097a6c0, 0x0)
google.golang.org/[email protected]/server.go:1620 +0xa1b
google.golang.org/grpc.(*Server).serveStreams.func1.2()
google.golang.org/[email protected]/server.go:922 +0x98
created by google.golang.org/grpc.(*Server).serveStreams.func1
google.golang.org/[email protected]/server.go:920 +0x28a
Error: The terraform-provider-github_v5.2.0 plugin crashed!
This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.
@0xBigBoss I have managed to reproduce this error when the credentials were invalid (expired in my case, but I assume it returns the same error for any invalid cred)
We're still using 4.26, but I just tested with 5.2.0 and works
I note that I can reproduce this error with valid credentials, and where we are able to update the custom branch rules via the web UI (meaning we have sufficient account privileges). Trying various options directly via the API seems to yield the same result.
See: https://github.com/orgs/community/discussions/30201#discussioncomment-3801138 for API request attempts.
@richchurcher as I have mentioned before, this issue is with the provider. If you are on GitHub Pro or Teams, you'll face the issue. It's completely unrelated to the creds validity. It's worth reading the whole tread, I also copied the code snippet that's responsible for the bug.
(On my previous message I was debugging the error raised a message above, trying to help someone to work around the issue with a temporary solution, and is also unrelated to the GitHub issue discussed in the tread)
Hope this helps.
Ended up upgrading to GitHub Enterprise to remove the blocker 🤷
For what it's worth. We are also facing this issue in our company.
I used the http-full provider to try to have this as automated as possible (terraform's http provider does not support put)
data "http" "github_repository_environment_environment" {
count = var.github_repository != "" ? 1 : 0
provider = http-full
url = "https://api.github.com/repos/${var.github_owner}/${var.github_repository}/environments/${var.environment}"
method = "PUT"
request_headers = {
Accept = "application/vnd.github+json"
Authorization= "Bearer ${var.github_token}"
}
request_body = <<EOF
{"deployment_branch_policy":{"protected_branches":true,"custom_branch_policies":false}}'
EOF
}
Then, in my secrets I have
depends_on = [data.http.github_repository_environment_environment]
Its not ideal, but it helps
I don't use any protection rules, I would like to be able to create a new environment like this:
curl -X PUT -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxx" \
https://api.github.com/repos/MyOrg/my_repo/environments/my_env -d '{}'
It'd be very useful if Github provider could support it otherwise I'll have to do some workaround.
The following would also help:
curl -X PUT -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxx" \
https://api.github.com/repos/MyOrg/my_repo/environments/my_env -d '{"deployment_branch_policy":{"protected_branches":false,"custom_branch_policies":true}}'
If anybody has interest in opening up a PR to fix this behavior, I'd be happy to review!
@kfcampbell I have opened the issue in go-github as the terraform provider uses their struct to make the API call.
They suggested to either add a flag or separate the feature into 2 API endpoints, but not sure how it would work on the provider side: Is there a meta argument I could access to check the caller's GitHub plan (to decide which API call we should be making)? I'm looking for something similar to isOrganization on the Owner struct.
An alternative solution can be if we error handle on 422 (aka the original call failed because we don't have enterprise) and make a second API call to the alternative endpoint?
An other, but less elegant solution can be if we let the terraform user decide whether they have the wait_timer feature available. We could add a has_wait_timer attribute to the resource (defaults to true, team/pro users would intentionally have to set this to false), and we add a flag / make API call to the alternative endpoint based on this value.
Is there a meta argument I could access to check the caller's GitHub plan (to decide which API call we should be making)?
There's not anything built into meta unfortunately:

Hmm...there's a GitHub Billing API but it doesn't look like what we're looking for either.
An alternative solution can be if we error handle on 422 (aka the original call failed because we don't have enterprise) and make a second API call to the alternative endpoint?
We do have a precedent for handling 422s like this here. It's definitely a little gross but it would be better than not solving the issue at all.
@kfcampbell got a PR out in go-github to fix the issue. Once it's merged we just have to upgrade the package here and it should work 🙂