terraform-provider-github
terraform-provider-github copied to clipboard
Deleting/Destroying an archived repo results in 403 error.
Hello,
I'm having issues trying to remove/destroy github repo's by either using terraform destroy
or after removing a module from the code and doing a terraform plan
on repo's which are archived. I have several archived repo's which i want to delete, but that isn't possible using terraform only right now when the archived
flag is set to true
. It complains about some resources that arn't able to be modified because the archive is in read-only state.
Terraform Version
Terraform v1.0.3
on linux_amd64
+ provider registry.terraform.io/gitlabhq/gitlab v3.7.0
+ provider registry.terraform.io/hashicorp/aws v3.52.0
+ provider registry.terraform.io/hashicorp/null v3.1.0
+ provider registry.terraform.io/integrations/github v4.13.0
Affected Resource(s)
At least the following, could be more:
- github_repository_collaborator
- github_repository
Terraform Configuration Files (as a module)
resource "github_repository" "repository" {
name = var.name
description = var.description
visibility = var.visibility
has_issues = var.issues
has_wiki = false
auto_init = var.auto_init
allow_squash_merge = var.allow_squash_merge
allow_rebase_merge = var.allow_rebase_merge
allow_merge_commit = var.allow_merge_commit
delete_branch_on_merge = var.delete_branch_on_merge
topics = var.topics
archived = var.archived
}
resource "github_repository_collaborator" "cicd-deployer_ro" {
count = var.allow_cicd-deployer_to_push == "true" ? 0 : 1
repository = github_repository.repository.name
username = "cicd-deployer"
permission = "pull"
}
resource "github_repository_collaborator" "cicd-deployer_rw" {
count = var.allow_cicd-deployer_to_push == "true" ? 1 : 0
repository = github_repository.repository.name
username = "cicd-deployer"
permission = "push"
}
Debug Output
Not able to provide actual debug output here, but the following line should be enough.
Error: DELETE https://api.github.com/repos/OWNER/REPO/collaborators/cicd-deployer: 403 Repository was archived so is read-only. []
Panic Output
n/a
Expected Behavior
Repository is deleted from github and nicely cleaned from terraform state.
Actual Behavior
The github provider returns an error that a specific resource is not being able to be deleted because the repository is set to read-only. If i manually delete the repo via github api call it works fine and all linked resources are removed by github.
Steps to Reproduce
Please list the steps required to reproduce the issue, for example:
- Use something like the above provided code.
- Have a
github_repository
and agithub_repository_collaborator
both configured.
-
terraform apply
- Configure that repo to be archived via the
archived
flag. -
terraform apply
- Either comment out that repo or use
terraform destroy
to remove that module. - It will error out because the repo is read-only and removing collaborators isn't possible.
Important Factoids
Non as far is a know, it happens at least on private repo's since that is where this is configured on.
References
n/a
While this is technically a bug, this appears to be a limitation of the way Terraform handles dependencies, mixed with the particular strategy this provider uses to handle different aspects of a repository's configuration, and a deficiency in the GitHub API.
The collaborator resources (in your configuration) "depend on" the repository resource. This means that they MUST be deleted before removing the repository. However, they cannot be deleted while the repository is archived. Also, the GitHub API does not support unarchiving a repository.
Even if it did, this problem would still partially exist. The collaborator resources should not override the repository's archived
setting, so you would have to terraform apply
the repository resource with archived = false
BEFORE applying a plan that destroys the resources.
There are really no good solutions to this at the moment, and there will likely never be a non-hacky solution that doesn't require two apply/destroy commands. Aside from just deleting it in GitHub, the best I can offer you is to do this when you want to delete an archived repo:
- Adjust any resources that depend on the
repository
to not depend on therepository
(in this case, changecollaborator
'srepository
to bevar.name
- Comment out/remove the
repository
-
terraform apply
- Comment out/remove the
collaborator
-
terraform apply
There is a also way to hack together a slightly more automated solution using some method to store state outside of terraform (or some hackery with terraform cloud). It's a pain and really, really, really gross, so I won't type it up unless you ask me to. It still isnt a one step solution for deletion, but it is only 3 steps.
I have a theory for a structure that would allow fully automated destroy plans on archived repository resources, but it has a lot of caveats and potentially dangerous operations, so I don't think it is viable. Also, it wouldn't work on remove-and-apply, only on destroy.
If the GitHub API ever supports unarchiving, this becomes simpler, but still 3 steps (just unarchive, apply, then delete everything)
If you can convince the terraform developers to massively overhaul the graph generation system to support a resource being created and deleted after the resource it depends on, that would be a one step solution to this problem.
Finally, depending on your tolerance for time, you can create a potentially nondeterministic, but fully automated, solution to this problem that takes advantage of the principles in the immediately preceding line:
- Adjust any resources that depend on the repo to not depend on the repo (in this case, change collaborator's
repository
to bevar.name
) - Create a
null_resource
resource - Create a sufficiently long***
time_sleep
resource - Create
depends_on
blocks in therepository
resource and thetime_sleep
resource that point to thenull_resource
resource - Create a
depends_on
block in pointing to thetime_sleep
resource in any resource that should depend on therepository
resource - Create a sufficiently long***
time_sleep
resource - Create a
depends_on
block in the newtime_sleep
resource that points to all of the resources in line 5 (except the repositoryresource
and the originaltime_sleep
resource) - Configure your Terraform CLI to run enough threads that the
repository
creation/destruction will always (at worst) run parallel with thetime_sleep
resource creation/destruction.
***: sufficiently long means:
- In line 3: the time it takes to create the repository
- In line 6: the time it takes to delete the repository
Also, just a general code suggestion: This:
variable "allow_cicd-deployer_to_push" {
// Whatever this is now
}
resource "github_repository_collaborator" "cicd-deployer_ro" {
count = var.allow_cicd-deployer_to_push == "true" ? 0 : 1
repository = github_repository.repository.name
username = "cicd-deployer"
permission = "pull"
}
resource "github_repository_collaborator" "cicd-deployer_rw" {
count = var.allow_cicd-deployer_to_push == "true" ? 1 : 0
repository = github_repository.repository.name
username = "cicd-deployer"
permission = "push"
}
should probably be this
variable "allow_cicd-deployer_to_push" {
// Whatever this was before, but with this change:
type = bool
}
resource "github_repository_collaborator" "cicd-deployer" {
repository = github_repository.repository.name
username = "cicd-deployer"
permission = var.allow_cicd-deployer_to_push ? "push" : "pull"
}
unless you have a veeeeeeeeery specific usecase where it won't work. Even then, the existence of that usecase probably indicates a larger problem that needs fixing.
👋 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!
The same problem happens with any other modification of the repo. I think archival should be executed last after any other changes.
E.g. I changed a description and added archive flag, and it failed with:
Repository was archived so is read-only.