Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repository environment creation error #1262

Closed
AlessandroLorenzi opened this issue Aug 24, 2022 · 19 comments · Fixed by #1463
Closed

Repository environment creation error #1262

AlessandroLorenzi opened this issue Aug 24, 2022 · 19 comments · Fixed by #1463
Labels
Status: Up for grabs Issues that are ready to be worked on by anyone Type: Bug Something isn't working as documented

Comments

@AlessandroLorenzi
Copy link

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:

  1. 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
  }
@ghost
Copy link

ghost commented Aug 25, 2022

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

@AlessandroLorenzi
Copy link
Author

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

@ti-atlastechnol
Copy link

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
  })

@AnitaErnszt
Copy link
Contributor

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.

@richchurcher
Copy link

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.

@avivek
Copy link

avivek commented Sep 20, 2022

Is this something that we can expect a quick fix for??
The jobs are left in a failed state always due to this issue.

@AnitaErnszt
Copy link
Contributor

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.

@0xBigBoss
Copy link

@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/terraform-plugin-sdk@v1.17.2/helper/schema/resource.go:470 +0x1aa
github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ReadResource(0xc000116a50, {0xc00058d0e0?, 0x10b3ba6?}, 0xc00058d0e0)
        github.com/hashicorp/terraform-plugin-sdk@v1.17.2/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/terraform-plugin-sdk@v1.17.2/internal/tfplugin5/tfplugin5.pb.go:3269 +0x170
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0002b0380, {0x1e8cea0, 0xc000682340}, 0xc00097a6c0, 0xc0003acc30, 0x2534710, 0x0)
        google.golang.org/grpc@v1.46.2/server.go:1283 +0xcfd
google.golang.org/grpc.(*Server).handleStream(0xc0002b0380, {0x1e8cea0, 0xc000682340}, 0xc00097a6c0, 0x0)
        google.golang.org/grpc@v1.46.2/server.go:1620 +0xa1b
google.golang.org/grpc.(*Server).serveStreams.func1.2()
        google.golang.org/grpc@v1.46.2/server.go:922 +0x98
created by google.golang.org/grpc.(*Server).serveStreams.func1
        google.golang.org/grpc@v1.46.2/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.

@AnitaErnszt
Copy link
Contributor

@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

@richchurcher
Copy link

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.

@richchurcher
Copy link

@AnitaErnszt
Copy link
Contributor

@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.

@ghost
Copy link

ghost commented Oct 5, 2022

Ended up upgrading to GitHub Enterprise to remove the blocker 🤷

@Konubinix
Copy link

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

@otavioribeiromedeiros
Copy link

otavioribeiromedeiros commented Nov 21, 2022

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}}'

@kfcampbell kfcampbell added Type: Bug Something isn't working as documented Status: Up for grabs Issues that are ready to be worked on by anyone Priority: Normal labels Nov 28, 2022
@kfcampbell
Copy link
Member

If anybody has interest in opening up a PR to fix this behavior, I'd be happy to review!

@AnitaErnszt
Copy link
Contributor

AnitaErnszt commented Dec 20, 2022

@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.

@kfcampbell
Copy link
Member

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:

image

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.

@AnitaErnszt
Copy link
Contributor

AnitaErnszt commented Jan 4, 2023

@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 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Up for grabs Issues that are ready to be worked on by anyone Type: Bug Something isn't working as documented
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants