Detect not-found via the error (errors.AsType) in github_team_repository delete#3524
Detect not-found via the error (errors.AsType) in github_team_repository delete#3524rilical wants to merge 2 commits into
Conversation
|
👋 Hi, and thank you for this contribution! This repo is maintained by GitHub and community members on a best-effort basis. We'll get to this as soon as we can. You can help us prioritize by joining the discussion on open issues and PRs, sharing details on the changes you need, and reviewing other contributions. 🤖 This is an automated message. |
stevehipwell
left a comment
There was a problem hiding this comment.
I've added a couple of inline comments, could you also look at the rest of the codebase for this pattern and make the relevant changes?
| _, err = client.Teams.RemoveTeamRepoByID(ctx, orgId, teamId, orgName, repoName) | ||
|
|
||
| if resp.StatusCode == 404 { | ||
| if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response != nil && ghErr.Response.StatusCode == http.StatusNotFound { |
There was a problem hiding this comment.
| if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response != nil && ghErr.Response.StatusCode == http.StatusNotFound { | |
| if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response.StatusCode == http.StatusNotFound { |
The response nil check is unnecessary as the type is a github.ErrorResponse and the response is always set (the pointer is to stop the struct being copied). Could you also remove where this pattern has been added to the codebase due to a Copilot review that I didn't fully validate.
There was a problem hiding this comment.
Done. Removed the nil check here and swept the same redundant guard everywhere it had crept in from earlier Copilot reviews:
github/util_retry.go(retryUntilResourceFound)github/provider.go(the org lookup, which had the invertedResponse == nil ||form)github/resource_github_enterprise_organization.go(isSAMLEnforcementError)
You're right that it's dead code: go-github only ever builds *github.ErrorResponse in CheckResponse as &ErrorResponse{Response: r} with a non-nil r, and the one place we construct it by hand (resource_github_team_members.go) sets Response too. Every other .Response.StatusCode deref in the package already skips the guard, so this just makes these consistent.
I also reworked the delete block to check for the error first and then use errors.AsType (matching resource_github_issue_label.go), and switched util_retry's literal 404 to http.StatusNotFound.
One thing I left alone: a bare 404 with no rename still returns the error through handleArchivedRepoDelete rather than being treated as idempotent (return nil) like issue_label/team_members, and I kept the repo-rename retry. Happy to make 404 a clean no-op and drop the rename lookup if that's the direction you want, just didn't want to change destroy semantics without a nod.
| // recovery branch, which issues a follow-up GET for the repository. Observing | ||
| // that second request proves the error-based 404 detection fired; if detection | ||
| // regressed, only the single delete request would be made. | ||
| func Test_resourceGithubTeamRepositoryDelete_notFoundTriggersRepositoryLookup(t *testing.T) { |
There was a problem hiding this comment.
I'm not 100% sure we need a test for these as we're going to see the same pattern in all of the resources.
There was a problem hiding this comment.
Removed it. I kept the panic regression test from #3518 (Test_resourceGithubTeamRepositoryDelete_nilResponseDoesNotPanic) since that covers a different path (a nil *Response on a transport error), but dropped the not-found lookup test since, like you said, that same pattern repeats across every resource.
454bbc7 to
1b9a459
Compare
|
sorry for the force-push, I accidentally committed a local state file ( |
|
@rilical do you want to rebase again? |
…ory delete Detect the not-found case in resourceGithubTeamRepositoryDelete from the returned error via errors.AsType[*github.ErrorResponse] instead of reading resp.StatusCode off the raw response, and restructure to check the error first, matching the delete style in resource_github_issue_label.go. The repository-rename recovery and archived-repository handling are unchanged. A *github.ErrorResponse always carries a non-nil Response (go-github only builds one in CheckResponse), so drop the redundant Response != nil guard here and at the other sites that had picked up the same pattern: util_retry.go, provider.go, and resource_github_enterprise_organization.go. Normalize util_retry.go's not-found check from the literal 404 to http.StatusNotFound. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1b9a459 to
cd9ce48
Compare
|
yep, done. rebased onto main now that #3518 landed, so it's down to just the single refactor commit. also refreshed the description to match. |
deiga
left a comment
There was a problem hiding this comment.
Looking at go-github it seems to me that a json.Unmarshal error can result in an github.ErrorResponse with a nil Response attribute. I don't think it makes sense to make the providers code more brittle by removing this nil checks
| repo, _, err := client.Repositories.Get(ctx, orgName, repoName) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| newRepoName := repo.GetName() | ||
| if newRepoName != repoName { | ||
| log.Printf("[INFO] Repo name has changed %s -> %s. "+ | ||
| "Try deleting team repository again.", | ||
| repoName, newRepoName) | ||
| _, err := client.Teams.RemoveTeamRepoByID(ctx, orgId, teamId, orgName, newRepoName) |
There was a problem hiding this comment.
issue: all of this is the unnecessary complexity Steve was talking about. This needs to go and the resource needs to be refactored to utilize the similar team renamed pattern as the repo renamed pattern being used
There was a problem hiding this comment.
Done, this is gone. Dropped the Repositories.Get + rename-and-retry block entirely and simplified delete to the same idempotent shape as resource_github_issue_label.go: a 404 from RemoveTeamRepoByID now returns nil (already gone), and anything else flows through the existing archived-repo handling. Behavior change worth calling out: a bare 404 on delete is now a no-op instead of surfacing an error. The #3518 nil-response panic test still covers the transport-error path and passes.
Per review, drop the Repositories.Get lookup and the rename-and-retry branch from resourceGithubTeamRepositoryDelete and simplify to the idempotent delete pattern used by resource_github_issue_label.go: a 404 from RemoveTeamRepoByID is treated as already-deleted (return nil), and any other error flows through handleArchivedRepoDelete as before. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
@deiga thanks for taking a look. I went through go-github v88 (the version pinned in go.mod) and I don't think that path exists there:
Every |
|
@rilical ah, Sorry. I didn't see Steve's comment. Yes, then the nil checks are safe to remove. |
Resolves #3523
Follow-up to #3518 (now merged), addressing @stevehipwell's review feedback.
What changed
resourceGithubTeamRepositoryDeletenow detects the not-found case from the returned error viaerrors.AsType[*github.ErrorResponse](err)instead of readingresp.StatusCodeoff the raw response, restructured to check the error first (matching the delete style inresource_github_issue_label.go).Response != nilguard on*github.ErrorResponseacross the codebase, since a*github.ErrorResponsealways carries a non-nilResponse(go-github only builds one inCheckResponse):util_retry.go,provider.go, andresource_github_enterprise_organization.go.util_retry.go's not-found check from the literal404tohttp.StatusNotFound.Behavior-preserving: the repo-rename retry and archived/404 handling are unchanged, and the nil-response panic regression test added in #3518 still covers this delete path.
Open question: a bare 404 on delete still returns the error rather than being idempotent (
return nil, likeresource_github_issue_label.go), and the rename retry is still there. Happy to simplify either if you'd like, I just didn't want to change destroy semantics unprompted.Verification
go build,go vet,gofmtclean.make test).TestAccGithubTeamRepositorypasses (create / read / import / update / destroy).Pull request checklist
Does this introduce a breaking change?
AI-assisted disclosure: developed with AI assistance (GitHub Copilot). Per the repository's AI Use Policy I have reviewed and understand the change, verified the
errors.AsType+*github.ErrorResponseinvariant against go-github v88's construction sites and the provider's usages, and tested it with the unit regression suite plus a live acceptance run ofTestAccGithubTeamRepository.