terraform-provider-github
terraform-provider-github copied to clipboard
Setting members_can_fork_private_repositories resets organisational fork policy
We're now using the github_organization_settings to configure some organisational settings (instead of "manual") and we noticed that settings members_can_fork_private_repositories works in unexpected ways with the organisational settings:
We had forking set to User accounts, imported the github_organization_settings resource (where members_can_fork_private_repositories apparantly is set to True and not TF changes this to the "Default" Organisations within this enterprise.
This is quite unexpected behaviour, and after reading up other issues decided to remove this setting from the resource entirely. When removing it TF actually said it would change the setting (update members_can_fork_private_repositories : true change to false). But the setting is now kept intact.
So:
- Organisation settings and Forking looks "off" (could be related to Enterprise)
- Is there a resource to change the forking policy of an (enterprise) organisation?
Related links:
- https://github.com/integrations/terraform-provider-github/issues/1199
- https://github.com/integrations/terraform-provider-github/issues/1333
- https://github.com/integrations/terraform-provider-github/pull/1362
I'm sorry, I'm not quite sure what you mean by:
This is quite unexpected behaviour, and after reading up other issues decided to remove this setting from the resource entirely. When removing it TF actually said it would change the setting (update members_can_fork_private_repositories : true change to false). But the setting is now kept intact.
Would you mind rephrasing this for me a little differently and I can try to help troubleshoot?
Hi @kfcampbell,
Organisation setting in the GUI:
Applying Terraform with the following (which gives no changes):
resource "github_organization_settings" "connectedbrewery" {
...
members_can_fork_private_repositories = true
...
}
👋 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!
Any update on this issue?
We use github_organization_settings with members_can_fork_private_repositories ~but are not seeing the sub-setting for the fork destination being reset by Terraform~ I spoke too soon - if the TF apply touches github_organization_settings, even though the change is not shown in the plan, it will reset the settings.
It would be good to be able to set this in TF instead of manually though.
+1 on this. Its less about being a bug and more about needing to add the feature of being able to select which rule to apply for forking private repos.
Also wanted to mention I took a quick look at the GitHub API and I don't see any field that actually sets the forking rule when enabling members_can_fork_private_repositories. So, this could end up being a limitation on the GitHub API.
https://docs.github.com/en/rest/orgs/orgs?apiVersion=2022-11-28#update-an-organization
I also tested some other scenarios directly on the API and here is what I've found so far:
- Submitting only
members_can_fork_private_repositories=falseresults expected behavior of disabling said property - Submitting only
members_can_fork_private_repositories=truewhen previous setting was false will enable said property with the first option selected. - Submitting only
members_can_fork_private_repositories=truewhen already set to true will reset the property back to the first option, regardless of what it was previously. - Submitting any other property by itself (I used
default_repository_permission=write) whilemembers_can_fork_private_repositories=trueAND selected any other option will not change the options selected formembers_can_fork_private_repositories - Submitting any other property (I used
default_repository_permission=write) ANDmembers_can_fork_private_repositories=truewill reset the property back to the first option, regardless of what it was previously.
So, without really digging into the code (because I suck at go), my assumption is that the provider is redundantly submitting members_can_fork_private_repositories: true regardless of changes to said property defined in the template.
I guess maybe the work around might be to exclude submitting this property if its already set to true, and only submit if it is changing from false to true.
Also, maybe creating a feature request or something to GitHub to update the management of this property, not sure how that is actually done. I am an enterprise customer so if I can help make this request, I'd be happy to.
Have any of the contributors been able to investigate this issue?
I've tried a lot of different approaches and here is a workaround which works for me for now.
It has to be run before and after terraform:
./enterprise-policies.sh unset
terraform apply # or tofu apply
./enterprise-policies.sh
#!/usr/bin/env bash
# enterprise-policies.sh
set -euo pipefail
# Configure enterprise settings which can't be done through GitHub Terraform Provider at the moment of writing this script
ENTERPRISE_SLUG="my-org"
usage() {
echo "Usage: $(basename "$0") [-h|--help|unset]"
echo
echo "Options:"
echo " -h, --help Display this help message"
echo " unset Disable enterprise policies"
}
graphql_request() {
local data=$1
local response; response=$(
curl -fsS -X POST \
-H "Authorization: bearer $GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-d "$data" \
https://api.github.com/graphql
)
local errors; errors=$(jq -r '(.errors // empty)[] | "ERROR: " + .message' <<< "$response")
if [[ -n "$errors" ]]; then
echo "$errors" >&2
return 1
fi
echo "$response"
}
get_enterprise_id() {
local slug=$1
local query='
query($slug: String!) {
enterprise(slug: $slug) {
id
}
}
'
local variables; variables=$(
jq -n \
--arg slug "$slug" \
'{
"slug": $slug
}'
)
local data; data=$(jq -n --arg query "$query" --arg variables "$variables" '{ query: $query, variables: $variables }')
graphql_request "$data" | jq -r .data.enterprise.id
}
enterprise_set_repo_forking_settings() {
local enterprise_id=$1
local action=${2:-ENABLED}
local query='
mutation($enterpriseId: ID!, $action: EnterpriseEnabledDisabledSettingValue!) {
updateEnterpriseAllowPrivateRepositoryForkingSetting(
input: {
enterpriseId: $enterpriseId,
settingValue: $action,
policyValue: USER_ACCOUNTS # Allow private repository forking only for user accounts
}
) {
message
}
}
'
local variables; variables=$(
jq -n \
--arg enterprise_id "$enterprise_id" \
--arg action "$action" \
'{
"enterpriseId": $enterprise_id,
"action": $action
}'
)
local data; data=$(jq -n --arg query "$query" --arg variables "$variables" '{ query: $query, variables: $variables }')
graphql_request "$data" | jq -r '"INFO: " + .data.updateEnterpriseAllowPrivateRepositoryForkingSetting.message'
}
main() {
[[ "$@" == "-h" || "$@" == "--help" ]] && { usage; exit 0; }
local enterprise_slug="$ENTERPRISE_SLUG"
local enterprise_id; enterprise_id=$(get_enterprise_id "$enterprise_slug")
if [[ "$#" -eq 0 ]]; then
enterprise_set_repo_forking_settings "$enterprise_id"
elif [[ "$@" == "unset" ]]; then
enterprise_set_repo_forking_settings "$enterprise_id" NO_POLICY
else
usage
exit 1
fi
}
main "$@"