terraform-provider-github
terraform-provider-github copied to clipboard
Some resource settings always change on apply
This is happening on existing resources that are imported in to Terraform. I haven't confirmed, but am guessing if they were new I would not see this behavior.
Terraform continuously updates several settings on resources on every apply. Viewing the settings in the UI reveals they are set correctly according to the configuration in Terraform.
If I terraform state pull
, edit the state to reflect these values that want to keep changing, and then push the state back, then it seems to stick. It no longer needs to update those attributes. I just updated one attribute to test that and it's stayed correct so far.
Terraform Version
Terraform v1.1.2
on darwin_amd64
+ provider registry.terraform.io/cloudposse/utils v0.17.10
+ provider registry.terraform.io/hashicorp/azurerm v2.90.0
+ provider registry.terraform.io/integrations/github v4.19.0
Affected Resource(s)
- github_repository
- github_branch_protection
Terraform Configuration Files
resource "github_repository" "this" {
name = var.name
description = var.description
visibility = "private"
allow_auto_merge = true
allow_merge_commit = true
allow_rebase_merge = false
allow_squash_merge = false
archive_on_destroy = true
auto_init = true
delete_branch_on_merge = true
has_downloads = false
has_issues = true
has_projects = false
has_wiki = true
vulnerability_alerts = true
lifecycle {
prevent_destroy = true
}
}
resource "github_branch_protection" "this" {
for_each = { for branch in var.protected_branches : branch.branch_name => branch }
repository_id = github_repository.this.node_id
pattern = each.value.branch_name
enforce_admins = true
allows_deletions = false
allows_force_pushes = false
require_conversation_resolution = true
required_pull_request_reviews {
dismiss_stale_reviews = true
required_approving_review_count = 1
}
required_status_checks {
strict = true
contexts = each.value.status_check_contexts
}
}
Expected Behavior
There should be no changes detected.
Actual Behavior
Terraform apply always has these changes to apply.
Terraform will perform the following actions:
# module.repos["foo"].github_repository.this will be updated in-place
~ resource "github_repository" "this" {
~ allow_auto_merge = false -> true
~ allow_merge_commit = false -> true
~ delete_branch_on_merge = false -> true
id = "foo"
name = "foo"
# (26 unchanged attributes hidden)
}
# module.repos["foo"].github_branch_protection.this["main"] will be updated in-place
~ resource "github_branch_protection" "this" {
~ enforce_admins = false -> true
id = "bar="
# (8 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
Plan: 0 to add, 2 to change, 0 to destroy.
Steps to Reproduce
-
terraform apply
I'm also hitting this issue with an upgrade to 4.19.0
4.18.2 does not have this issue.
Hmm, possibly related to the branch protection updates we shipped over in v4.19.0, but it is not immediately obvious to me how 🤔
I've tested with 4.18.2 and I still get the problem:
# github_repository.org_configuration will be updated in-place
~ resource "github_repository" "org_configuration" {
~ allow_auto_merge = false -> true
id = "org-configuration"
name = "org-configuration"
# (26 unchanged attributes hidden)
}
The allow_auto_merge
is always flagged to false -> true
.
If I check manually the option on the web UI, terraform apply
will uncheck it.
$ terraform version
Terraform v1.1.4
on darwin_amd64
+ provider registry.terraform.io/integrations/github v4.18.2
GitHub Enterprise Server 3.1.14
I can confirm with GHES 3.2.10, Terraform 1.1.7, and provider v4.20.1.
Running TF_LOG=DEBUG terraform apply
you can see:
# module.repository_devops-example.github_repository.repository will be updated in-place
~ resource "github_repository" "repository" {
~ allow_auto_merge = false -> true
id = "devops-example"
name = "devops-example"
# (26 unchanged attributes hidden)
}
=> yes
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: 2022/03/22 11:03:25 [DEBUG] Github API Request Details:
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: ---[ REQUEST ]---------------------------------------
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: PATCH /api/v3/repos/<redacted>/devops-example HTTP/1.1
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Host: <redacted>
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: User-Agent: go-github
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Content-Length: 370
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Accept: application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Content-Type: application/json
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Accept-Encoding: gzip
[DEBUG] provider.terraform-provider-github_v4.20.1.exe:
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: {
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: "name": "devops-example",
...
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: "allow_auto_merge": true,
...
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: }
and later
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: 2022/03/22 11:03:28 [DEBUG] Github API Response Details:
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: ---[ RESPONSE ]--------------------------------------
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: HTTP/2.0 200 OK
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Access-Control-Allow-Origin: *
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining
, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
[WARN] Provider "provider[\"registry.terraform.io/integrations/github\"]" produced an unexpected new value for module.repository_devops-sonarqube-test.github_repository.repository, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .etag: was cty.StringVal("W/\"f8...03\""), but now cty.StringVal("W/\"81...0a\"")
- .allow_auto_merge: was cty.True, but now cty.False
[DEBUG] provider.terraform-provider-github_v4.20.1.exe: Cache-Control: private, max-age=60, s-maxage=60
[WARN] Provider "provider[\"registry.terraform.io/integrations/github\"]" produced an unexpected new value for module.repository_devops-example.github_repository.repository, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .etag: was cty.StringVal("W/\"34...5d\""), but now cty.StringVal("W/\"cb...a5\"")
- .allow_auto_merge: was cty.True, but now cty.False
Furthermore, there's this in the state:
{
"module": "module.repository_devops-example",
"mode": "managed",
"type": "github_repository",
"name": "repository",
"provider": "provider[\"registry.terraform.io/integrations/github\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"allow_auto_merge": false,
"allow_merge_commit": false,
"allow_rebase_merge": false,
...
Regarding the first posts'
This is happening on existing resources that are imported in to Terraform. I haven't confirmed, but am guessing if they were new I would not see this behavior.
adding a new repository:
# module.repository_devops-new-example.github_repository.repository will be created
+ resource "github_repository" "repository" {
+ allow_auto_merge = true
+ allow_merge_commit = false
+ allow_rebase_merge = false
+ allow_squash_merge = true
...
+ id = (known after apply)
+ name = "devops-new-example"
...
}
=> yes
[WARN] Provider "provider[\"registry.terraform.io/integrations/github\"]" produced an unexpected new value for module.repository_devops-new-example.github_repository.repository, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .homepage_url: was null, but now cty.StringVal("")
- .description: was null, but now cty.StringVal("")
- .allow_auto_merge: was cty.True, but now cty.False
- .vulnerability_alerts: was null, but now cty.False
- .has_downloads: was null, but now cty.False
- .is_template: was null, but now cty.False
So, it is also not working for new repositories (I can confirm via web ui that the checkbox is unchecked).
Downgrading to provider 4.18.2 as suggested:
[DEBUG] provider.terraform-provider-github_v4.18.2.exe: X-Github-Enterprise-Version: 3.2.10
[WARN] Provider "provider[\"registry.terraform.io/integrations/github\"]" produced an unexpected new value for module.repository_devops-example.github_repository.repository, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .allow_auto_merge: was cty.True, but now cty.False
- .etag: was cty.StringVal("W/\"c5...9f\""), but now cty.StringVal("W/\"96...a3\"")
Same for the newly created repository.
Downgrading to 4.17.0 (in which allow_auto_merge
was added):
[DEBUG] provider.terraform-provider-github_v4.17.0.exe: X-Github-Enterprise-Version: 3.2.10
[WARN] Provider "provider[\"registry.terraform.io/integrations/github\"]" produced an unexpected new value for module.repository_devops-example.github_repository.repository, but we are tolerating it because it is using the legacy plugin SDK.
The following problems may be the cause of any confusing errors from downstream operations:
- .etag: was cty.StringVal("W/\"96...a3\""), but now cty.StringVal("W/\"1f...f5\"")
- .allow_auto_merge: was cty.True, but now cty.False
Same same :(
Downgrading to Terraform 1.0.11 (out of curiousity) returns the same result.
@jcudit any idea what else we can try to solve this issue?
I think I'm experiencing the same problem:
~ resource "github_branch_protection" "protect-main" {
id = "redacted"
# (9 unchanged attributes hidden)
~ required_pull_request_reviews {
~ dismiss_stale_reviews = false -> true
~ require_code_owner_reviews = true -> false
# (3 unchanged attributes hidden)
}
- required_status_checks {
- contexts = [] -> null
- strict = true -> null
}
}
This appears for all our branch protection rules on every apply, and the changes are never actually made. If I make the changes manually, they do disappear here though.
Interesting fact: setting allow_auto_merge
via simple API call is also not working:
curl -X PATCH -u '<redacted>' -H 'Accept: application/vnd.github.v3+json' https://<redacted>/api/v3/repos/<redacted>/devops-example -d '{"allow_auto_merge": true}'
In fact, the answer is not even containing the allow_auto_merge
attribute:
{
"id": <redacted>,
"node_id": "<redacted>",
"name": "devops-example",
"full_name": "<redacted>/devops-example",
"private": true,
"owner": {
"login": "<redacted>",
"id": <redacted>,
"node_id": "<redacted>",
"avatar_url": "<redacted>/avatars/u/<redacted>?",
"gravatar_id": "",
"url": "<redacted>/api/v3/users/<redacted>",
"html_url": "<redacted>/<redacted>",
"followers_url": "<redacted>/api/v3/users/<redacted>/followers",
"following_url": "<redacted>/api/v3/users/<redacted>/following{/other_user}",
"gists_url": "<redacted>/api/v3/users/<redacted>/gists{/gist_id}",
"starred_url": "<redacted>/api/v3/users/<redacted>/starred{/owner}{/repo}",
"subscriptions_url": "<redacted>/api/v3/users/<redacted>/subscriptions",
"organizations_url": "<redacted>/api/v3/users/<redacted>/orgs",
"repos_url": "<redacted>/api/v3/users/<redacted>/repos",
"events_url": "<redacted>/api/v3/users/<redacted>/events{/privacy}",
"received_events_url": "<redacted>/api/v3/users/<redacted>/received_events",
"type": "Organization",
"site_admin": false
},
"html_url": "<redacted>/<redacted>/devops-example",
"description": null,
"fork": false,
"url": "<redacted>/api/v3/repos/<redacted>/devops-example",
"forks_url": "<redacted>/api/v3/repos/<redacted>/devops-example/forks",
"keys_url": "<redacted>/api/v3/repos/<redacted>/devops-example/keys{/key_id}",
"collaborators_url": "<redacted>/api/v3/repos/<redacted>/devops-example/collaborators{/collaborator}",
"teams_url": "<redacted>/api/v3/repos/<redacted>/devops-example/teams",
"hooks_url": "<redacted>/api/v3/repos/<redacted>/devops-example/hooks",
"issue_events_url": "<redacted>/api/v3/repos/<redacted>/devops-example/issues/events{/number}",
"events_url": "<redacted>/api/v3/repos/<redacted>/devops-example/events",
"assignees_url": "<redacted>/api/v3/repos/<redacted>/devops-example/assignees{/user}",
"branches_url": "<redacted>/api/v3/repos/<redacted>/devops-example/branches{/branch}",
"tags_url": "<redacted>/api/v3/repos/<redacted>/devops-example/tags",
"blobs_url": "<redacted>/api/v3/repos/<redacted>/devops-example/git/blobs{/sha}",
"git_tags_url": "<redacted>/api/v3/repos/<redacted>/devops-example/git/tags{/sha}",
"git_refs_url": "<redacted>/api/v3/repos/<redacted>/devops-example/git/refs{/sha}",
"trees_url": "<redacted>/api/v3/repos/<redacted>/devops-example/git/trees{/sha}",
"statuses_url": "<redacted>/api/v3/repos/<redacted>/devops-example/statuses/{sha}",
"languages_url": "<redacted>/api/v3/repos/<redacted>/devops-example/languages",
"stargazers_url": "<redacted>/api/v3/repos/<redacted>/devops-example/stargazers",
"contributors_url": "<redacted>/api/v3/repos/<redacted>/devops-example/contributors",
"subscribers_url": "<redacted>/api/v3/repos/<redacted>/devops-example/subscribers",
"subscription_url": "<redacted>/api/v3/repos/<redacted>/devops-example/subscription",
"commits_url": "<redacted>/api/v3/repos/<redacted>/devops-example/commits{/sha}",
"git_commits_url": "<redacted>/api/v3/repos/<redacted>/devops-example/git/commits{/sha}",
"comments_url": "<redacted>/api/v3/repos/<redacted>/devops-example/comments{/number}",
"issue_comment_url": "<redacted>/api/v3/repos/<redacted>/devops-example/issues/comments{/number}",
"contents_url": "<redacted>/api/v3/repos/<redacted>/devops-example/contents/{+path}",
"compare_url": "<redacted>/api/v3/repos/<redacted>/devops-example/compare/{base}...{head}",
"merges_url": "<redacted>/api/v3/repos/<redacted>/devops-example/merges",
"archive_url": "<redacted>/api/v3/repos/<redacted>/devops-example/{archive_format}{/ref}",
"downloads_url": "<redacted>/api/v3/repos/<redacted>/devops-example/downloads",
"issues_url": "<redacted>/api/v3/repos/<redacted>/devops-example/issues{/number}",
"pulls_url": "<redacted>/api/v3/repos/<redacted>/devops-example/pulls{/number}",
"milestones_url": "<redacted>/api/v3/repos/<redacted>/devops-example/milestones{/number}",
"notifications_url": "<redacted>/api/v3/repos/<redacted>/devops-example/notifications{?since,all,participating}",
"labels_url": "<redacted>/api/v3/repos/<redacted>/devops-example/labels{/name}",
"releases_url": "<redacted>/api/v3/repos/<redacted>/devops-example/releases{/id}",
"deployments_url": "<redacted>/api/v3/repos/<redacted>/devops-example/deployments",
"created_at": "2021-04-14T09:35:52Z",
"updated_at": "2022-03-22T10:43:20Z",
"pushed_at": "2022-03-22T13:00:09Z",
"git_url": "git://<redacted>/<redacted>/devops-example.git",
"ssh_url": "git@<redacted>:<redacted>/devops-example.git",
"clone_url": "<redacted>/<redacted>/devops-example.git",
"svn_url": "<redacted>/<redacted>/devops-example",
"homepage": "",
"size": 38,
"stargazers_count": 0,
"watchers_count": 0,
"language": "Java",
"has_issues": false,
"has_projects": false,
"has_downloads": false,
"has_wiki": false,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 2,
"license": null,
"forks": 0,
"open_issues": 2,
"watchers": 0,
"default_branch": "main",
"permissions": {
"admin": true,
"maintain": true,
"push": true,
"triage": true,
"pull": true
},
"allow_squash_merge": true,
"allow_merge_commit": false,
"allow_rebase_merge": false,
"delete_branch_on_merge": true,
"organization": {
"login": "<redacted>",
"id": <redacted>,
"node_id": "<redacted>",
"avatar_url": "<redacted>/avatars/u/<redacted>?",
"gravatar_id": "",
"url": "<redacted>/api/v3/users/<redacted>",
"html_url": "<redacted>/<redacted>",
"followers_url": "<redacted>/api/v3/users/<redacted>/followers",
"following_url": "<redacted>/api/v3/users/<redacted>/following{/other_user}",
"gists_url": "<redacted>/api/v3/users/<redacted>/gists{/gist_id}",
"starred_url": "<redacted>/api/v3/users/<redacted>/starred{/owner}{/repo}",
"subscriptions_url": "<redacted>/api/v3/users/<redacted>/subscriptions",
"organizations_url": "<redacted>/api/v3/users/<redacted>/orgs",
"repos_url": "<redacted>/api/v3/users/<redacted>/repos",
"events_url": "<redacted>/api/v3/users/<redacted>/events{/privacy}",
"received_events_url": "<redacted>/api/v3/users/<redacted>/received_events",
"type": "Organization",
"site_admin": false
},
"network_count": 0,
"subscribers_count": 0
}
...which explains, why Terraform is recognizing the option as set to false
.
I'll contact the GitHub support to clarify why the API is not working in GHES 3.2.10.
I have also the same problem, it doesn't show the changes in the plan, but definitely always reset the two attributes:
allow_auto_merge
delete_branch_on_merge
Even if I use the ignore_changes lifecycle (Provider version: 4.28.0)
I am having the same problem (Provider version 4.29.0) I think it might be an authentication/permissions issue which causes data to be missing from api calls. It works with if I use PAT locally, but not when using a GitHub App
GitHub confirmed the GHES version is the root cause. It is not working with GHES 3.2, it starts working with GHES >= 3.3.
Hi,
same problem here, Provider 4.28.0. I can confirm that it occurs with the Github App, it works flawlessly with the personal access token.
We are on the Github free cloud plan, so it's not only related to GHES.
Joining in to confirm the symptoms:
- State doesn't reflect the reality, even after a
terraform state refresh
- Applies show the same changes over and over, even if it successfully applies them
- Affects the
github_repository
andgithub_branch_protection
resources
As pointed by @jazzlyn and now that it's mentioned, the issue was not showing up when using personnal access tokens; it started when we switched to a GitHub App.
- Provider version:
5.11.0
- Terraform version:
1.3.6
I think I'm hitting the same issue, every Terraform plan shows this for every repository:
# github_repository.repository will be updated in-place
~ resource "github_repository" "repository" {
~ allow_merge_commit = false -> true
~ delete_branch_on_merge = false -> true
id = "repository_name"
+ merge_commit_message = "PR_TITLE"
+ merge_commit_title = "MERGE_MESSAGE"
name = "repository_name"
+ squash_merge_commit_message = "COMMIT_MESSAGES"
+ squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
# (27 unchanged attributes hidden)
}
I have ~ 30 repositories all configured the same and every one shows the same diff on plan, yet (at least for allow_merge_commit
& delete_branch_on_merge
) those settings are correctly enabled in the repository settings.
- Provider version: 5.18.0 (also using App authentication)
- Terraform version: 1.3.9
I'm currently configuring the provider like so:
provider "github" {
owner = "MyOrg"
app_auth {
installation_id = "12345678"
}
}
I'm then exporting the GITHUB_APP_ID
and GITHUB_APP_PEM_FILE
environment variables to finish configuring the provider. If I change the provider like so:
provider "github" {
owner = "MyOrg"
# app_auth {
# installation_id = "12345678"
# }
}
and then export GITHUB_TOKEN
with a classic PAT scoped to admin:org
and repo
then my plans go back to being a no-op. So it definitely seems related to PAT vs App auth. Is this a GitHub bug perhaps?
My App has the following permissions:
- Repository: Administration R/W, Metadata R/O
- Organization: Administration R/W, Members R/W, Organization dependabot secrets R/W, Secrets R/W
I can't use a new Fine-grained PAT scoped to the same permissions as that doesn't work with the GraphQL API.
I've done some more digging. Using the following command:
curl -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <TOKEN>" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/MyOrg/my-repo
I run the command once with a PAT, and again using an access token obtained through my App following this documentation. Here's the difference in output:
--- PAT 2023-03-14 15:28:16.947431000 +0000
+++ APP 2023-03-14 15:51:47.137431000 +0000
@@ -100,24 +100,12 @@
"watchers": 0,
"default_branch": "master",
"permissions": {
- "admin": true,
- "maintain": true,
- "push": true,
- "triage": true,
- "pull": true
+ "admin": false,
+ "maintain": false,
+ "push": false,
+ "triage": false,
+ "pull": false
},
- "temp_clone_token": "XXX",
- "allow_squash_merge": false,
- "allow_merge_commit": true,
- "allow_rebase_merge": false,
- "allow_auto_merge": false,
- "delete_branch_on_merge": true,
- "allow_update_branch": false,
- "use_squash_pr_title_as_default": false,
- "squash_merge_commit_message": "COMMIT_MESSAGES",
- "squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
- "merge_commit_message": "PR_TITLE",
- "merge_commit_title": "MERGE_MESSAGE",
"organization": {
"login": "MyOrg",
"id": 12345678,
So you can see all the problematic fields just aren't returned by the API when using an App to authenticate but are present when using a PAT. Terraform cannot possibly work if the API has this behaviour.
I contacted GitHub support about this. Adding the Repository Contents R/W permission to the App permissions fixes it; my Terraform runs are now no-ops once more.
This seems slightly counter-intuitive as my App has now gained the ability to push contents in order to retrieve what are essentially repository settings. I'm checking with GitHub support if this is indeed the intended behaviour.
Chiming in to say I'm also currently hitting this issue. It is not an absolute blocker, but it is of course annoying to mentally filter out part of the plan as "not really changes."
With a fine-grained token, I get
401 Unauthorized body: "{\"message\":\"Personal access tokens with fine grained access do not support the GraphQL API\",\"documentation_url\":\"https://docs.github.com/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql\"}"
I don't have an App, just running from the repository. Thanks for the detective work @bodgit
So I finally got a response from GitHub support:
On github.com, only users with push access can figure out which merge options are available because only users with push access can merge pull requests and see which options are provided by the UI. The REST API is behaving the same way the website UI does.
So it looks like this is why the App needs to have contents R/W permission, in order just to see which merge options are available.
Hmm...we could start with a docs fix for now. I'm not sure what a good option would be for behavior in the provider.
Thank you so much for the investigation @bodgit - I was able to fix this error to the repo by the fine grained permission "contents" with r/w
👋 Hey Friends, this issue has been automatically marked as stale
because it has no recent activity. It will be closed if no further activity occurs. Please add the Status: Pinned
label if you feel that this issue needs to remain open/active. Thank you for your contributions and help in keeping things tidy!